From 2f5ef0854c0fcdef6748a437b96d993e5ffdfe20 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 27 Mar 2025 08:11:09 +0700 Subject: [PATCH 01/18] added in token payment info --- .../document_base_transition/fields.rs | 1 + .../document_base_transition/mod.rs | 5 + .../document_base_transition/v0/mod.rs | 17 +-- .../document_base_transition/v0/v0_methods.rs | 7 + .../document_base_transition/v0_methods.rs | 15 ++ .../v1/from_document.rs | 21 +++ .../document_base_transition/v1/mod.rs | 91 +++++++++++++ .../document_base_transition/v1/v1_methods.rs | 80 +++++++++++ .../document_base_transition/v1_methods.rs | 33 +++++ .../document_create_transition/convertible.rs | 10 +- .../document_create_transition/v0/mod.rs | 18 +-- .../rs-dpp/src/tokens/gas_fees_paid_by.rs | 19 +++ packages/rs-dpp/src/tokens/mod.rs | 2 + .../src/tokens/token_payment_info/mod.rs | 116 ++++++++++++++++ .../src/tokens/token_payment_info/v0/mod.rs | 125 +++++++++++++++++ .../token_payment_info/v0/v0_accessors.rs | 42 ++++++ .../data_contract_update/state/v0/mod.rs | 1 - .../transformer.rs | 25 ++-- .../document_base_transition_action/v0/mod.rs | 8 +- .../v0/transformer.rs | 46 +++---- .../token_transition/mod.rs | 1 - .../transformer.rs | 128 +++++++----------- .../v0/transformer.rs | 99 ++++---------- .../btreemap_removal_extensions.rs | 74 ++++++++++ 24 files changed, 766 insertions(+), 218 deletions(-) create mode 100644 packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs create mode 100644 packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs create mode 100644 packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs create mode 100644 packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs create mode 100644 packages/rs-dpp/src/tokens/gas_fees_paid_by.rs create mode 100644 packages/rs-dpp/src/tokens/token_payment_info/mod.rs create mode 100644 packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs create mode 100644 packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/fields.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/fields.rs index df730f10f96..8ba3d4b2441 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/fields.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/fields.rs @@ -4,6 +4,7 @@ pub(in crate::state_transition::state_transitions::document::batch_transition) m pub const DOCUMENT_TYPE: &str = "$type"; pub const ACTION: &str = "$action"; pub const IDENTITY_CONTRACT_NONCE: &str = "$identityContractNonce"; + pub const TOKEN_PAYMENT_INFO: &str = "$tokenPaymentInfo"; } pub const IDENTIFIER_FIELDS: [&str; 2] = [property_names::ID, property_names::DATA_CONTRACT_ID]; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs index d430a12ba79..aeb16a1e0d4 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs @@ -3,6 +3,8 @@ mod fields; mod from_document; pub mod v0; mod v0_methods; +pub mod v1; +mod v1_methods; #[cfg(any( feature = "state-transition-value-conversion", @@ -31,6 +33,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; #[cfg(feature = "state-transition-value-conversion")] use std::collections::BTreeMap; +use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; #[derive(Debug, Clone, Encode, Decode, PartialEq, Display, From)] #[cfg_attr( @@ -40,6 +43,8 @@ use std::collections::BTreeMap; pub enum DocumentBaseTransition { #[display("V0({})", "_0")] V0(DocumentBaseTransitionV0), + #[display("V1({})", "_1")] + V1(DocumentBaseTransitionV1), } impl Default for DocumentBaseTransition { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs index 9477075d480..6b4b5148815 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs @@ -46,7 +46,7 @@ pub struct DocumentBaseTransitionV0 { pub id: Identifier, #[cfg_attr( feature = "state-transition-serde-conversion", - serde(rename = "$identity-contract-nonce") + serde(rename = "$identityContractNonce") )] pub identity_contract_nonce: IdentityNonce, /// Name of document type found int the data contract associated with the `data_contract_id` @@ -69,16 +69,13 @@ impl DocumentBaseTransitionV0 { ) -> Result { Ok(DocumentBaseTransitionV0 { id: Identifier::from( - map.remove_hash256_bytes(property_names::ID) - .map_err(ProtocolError::ValueError)?, + map.remove_hash256_bytes(property_names::ID)?, ), identity_contract_nonce, document_type_name: map - .remove_string(property_names::DOCUMENT_TYPE) - .map_err(ProtocolError::ValueError)?, + .remove_string(property_names::DOCUMENT_TYPE)?, data_contract_id: Identifier::new( - map.remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID) - .map_err(ProtocolError::ValueError)? + map.remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID)? .unwrap_or(data_contract.id().to_buffer()), ), }) @@ -94,7 +91,7 @@ pub trait DocumentTransitionObjectLike { data_contract: DataContract, ) -> Result where - Self: std::marker::Sized; + Self: Sized; #[cfg(feature = "state-transition-value-conversion")] /// Creates the document transition from Raw Object fn from_object( @@ -102,14 +99,14 @@ pub trait DocumentTransitionObjectLike { data_contract: DataContract, ) -> Result where - Self: std::marker::Sized; + Self: Sized; #[cfg(feature = "state-transition-value-conversion")] fn from_value_map( map: BTreeMap, data_contract: DataContract, ) -> Result where - Self: std::marker::Sized; + Self: Sized; #[cfg(feature = "state-transition-value-conversion")] /// Object is an [`platform::Value`] instance that preserves the `Vec` representation diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/v0_methods.rs index f3c6beb7ee1..6047dcf6586 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/v0_methods.rs @@ -14,6 +14,9 @@ pub trait DocumentBaseTransitionV0Methods { /// Returns the document type name. fn document_type_name(&self) -> &String; + /// Returns the document type name as owned. + fn document_type_name_owned(self) -> String; + /// Sets the document type name. fn set_document_type_name(&mut self, document_type_name: String); @@ -40,6 +43,10 @@ impl DocumentBaseTransitionV0Methods for DocumentBaseTransitionV0 { &self.document_type_name } + fn document_type_name_owned(self) -> String { + self.document_type_name + } + fn set_document_type_name(&mut self, document_type_name: String) { self.document_type_name = document_type_name; } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0_methods.rs index 053865b0568..b556e2fee80 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0_methods.rs @@ -9,54 +9,69 @@ impl DocumentBaseTransitionV0Methods for DocumentBaseTransition { fn id(&self) -> Identifier { match self { DocumentBaseTransition::V0(v0) => v0.id(), + DocumentBaseTransition::V1(v1) => v1.id(), } } fn set_id(&mut self, id: Identifier) { match self { DocumentBaseTransition::V0(v0) => v0.set_id(id), + DocumentBaseTransition::V1(v1) => v1.set_id(id), } } fn document_type_name(&self) -> &String { match self { DocumentBaseTransition::V0(v0) => v0.document_type_name(), + DocumentBaseTransition::V1(v1) => v1.document_type_name(), + } + } + fn document_type_name_owned(self) -> String { + match self { + DocumentBaseTransition::V0(v0) => v0.document_type_name_owned(), + DocumentBaseTransition::V1(v1) => v1.document_type_name_owned(), } } fn set_document_type_name(&mut self, document_type_name: String) { match self { DocumentBaseTransition::V0(v0) => v0.set_document_type_name(document_type_name), + DocumentBaseTransition::V1(v1) => v1.set_document_type_name(document_type_name), } } fn data_contract_id(&self) -> Identifier { match self { DocumentBaseTransition::V0(v0) => v0.data_contract_id(), + DocumentBaseTransition::V1(v1) => v1.data_contract_id(), } } fn data_contract_id_ref(&self) -> &Identifier { match self { DocumentBaseTransition::V0(v0) => v0.data_contract_id_ref(), + DocumentBaseTransition::V1(v1) => v1.data_contract_id_ref(), } } fn set_data_contract_id(&mut self, data_contract_id: Identifier) { match self { DocumentBaseTransition::V0(v0) => v0.set_data_contract_id(data_contract_id), + DocumentBaseTransition::V1(v1) => v1.set_data_contract_id(data_contract_id), } } fn identity_contract_nonce(&self) -> IdentityNonce { match self { DocumentBaseTransition::V0(v0) => v0.identity_contract_nonce, + DocumentBaseTransition::V1(v1) => v1.identity_contract_nonce, } } fn set_identity_contract_nonce(&mut self, identity_contract_nonce: IdentityNonce) { match self { DocumentBaseTransition::V0(v0) => v0.identity_contract_nonce = identity_contract_nonce, + DocumentBaseTransition::V1(v1) => v1.identity_contract_nonce = identity_contract_nonce, } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs new file mode 100644 index 00000000000..c457db10a44 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs @@ -0,0 +1,21 @@ +use crate::data_contract::document_type::accessors::DocumentTypeV0Getters; +use crate::data_contract::document_type::DocumentTypeRef; +use crate::document::{Document, DocumentV0Getters}; +use crate::prelude::IdentityNonce; +use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; + +impl DocumentBaseTransitionV1 { + pub(in crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_base_transition) fn from_document( + document: &Document, + document_type: DocumentTypeRef, + identity_contract_nonce: IdentityNonce, + ) -> Self { + DocumentBaseTransitionV1 { + id: document.id(), + identity_contract_nonce, + document_type_name: document_type.name().to_string(), + data_contract_id: document_type.data_contract_id(), + token_payment_info: None, + } + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs new file mode 100644 index 00000000000..7edf1bc23b1 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs @@ -0,0 +1,91 @@ +pub mod from_document; +pub mod v1_methods; + +#[cfg(feature = "state-transition-value-conversion")] +use std::collections::BTreeMap; + +use bincode::{Decode, Encode}; +use derive_more::Display; + +#[cfg(feature = "state-transition-value-conversion")] +use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; +#[cfg(feature = "state-transition-value-conversion")] +use platform_value::Value; +#[cfg(feature = "state-transition-serde-conversion")] +use serde::{Deserialize, Serialize}; +#[cfg(feature = "state-transition-value-conversion")] +use crate::data_contract::accessors::v0::DataContractV0Getters; +use crate::identifier::Identifier; +use crate::prelude::IdentityNonce; +#[cfg(feature = "state-transition-value-conversion")] +use crate::state_transition::batch_transition::document_base_transition::property_names; +#[cfg(any( + feature = "state-transition-json-conversion", + feature = "state-transition-value-conversion" +))] +use crate::{data_contract::DataContract, errors::ProtocolError}; +use crate::tokens::token_payment_info::TokenPaymentInfo; + +#[derive(Debug, Clone, Encode, Decode, Default, PartialEq, Display)] +#[cfg_attr( + feature = "state-transition-serde-conversion", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] +#[display( + "ID: {}, Type: {}, Contract ID: {}", + "id", + "document_type_name", + "data_contract_id" +)] +pub struct DocumentBaseTransitionV1 { + /// The document ID + #[cfg_attr(feature = "state-transition-serde-conversion", serde(rename = "$id"))] + pub id: Identifier, + #[cfg_attr( + feature = "state-transition-serde-conversion", + serde(rename = "$identityContractNonce") + )] + pub identity_contract_nonce: IdentityNonce, + /// Name of document type found int the data contract associated with the `data_contract_id` + #[cfg_attr(feature = "state-transition-serde-conversion", serde(rename = "$type"))] + pub document_type_name: String, + /// Data contract ID generated from the data contract's `owner_id` and `entropy` + #[cfg_attr( + feature = "state-transition-serde-conversion", + serde(rename = "$dataContractId") + )] + pub data_contract_id: Identifier, + /// An optional Token Payment Info + #[cfg_attr( + feature = "state-transition-serde-conversion", + serde(default, rename = "$tokenPaymentInfo") + )] + pub token_payment_info: Option +} + +#[cfg(feature = "state-transition-value-conversion")] +impl DocumentBaseTransitionV1 { + pub fn from_value_map_consume( + map: &mut BTreeMap, + data_contract: DataContract, + identity_contract_nonce: IdentityNonce, + ) -> Result { + let inner_token_payment_info_map: Option> = map.remove_optional_map_as_btree_map_keep_values_as_platform_value(property_names::TOKEN_PAYMENT_INFO).ok().flatten(); + Ok(DocumentBaseTransitionV1 { + id: Identifier::from( + map.remove_hash256_bytes(property_names::ID)?, + ), + identity_contract_nonce, + document_type_name: map + .remove_string(property_names::DOCUMENT_TYPE)?, + data_contract_id: Identifier::new( + map.remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID)? + .unwrap_or(data_contract.id().to_buffer()), + ), + token_payment_info: inner_token_payment_info_map.map(|map| { + map.try_into() + }).transpose()?, + }) + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs new file mode 100644 index 00000000000..5c75fdfba33 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs @@ -0,0 +1,80 @@ +use crate::prelude::IdentityNonce; +use platform_value::Identifier; +use crate::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; +use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; +use crate::tokens::token_payment_info::TokenPaymentInfo; + +/// A trait that contains getter and setter methods for `DocumentBaseTransitionV0` +pub trait DocumentBaseTransitionV1Methods : DocumentBaseTransitionV0Methods { + /// Returns the token payment info. + fn token_payment_info(&self) -> Option; + + /// Returns the token payment info. + fn token_payment_info_ref(&self) -> &Option; + + /// Sets the token payment info. + fn set_token_payment_info(&mut self, token_payment_info: TokenPaymentInfo); + + /// Clears the token payment info. + fn clear_token_payment_info(&mut self); +} + +impl DocumentBaseTransitionV1Methods for DocumentBaseTransitionV1 { + fn token_payment_info(&self) -> Option { + self.token_payment_info + } + + fn token_payment_info_ref(&self) -> &Option { + &self.token_payment_info + } + + fn set_token_payment_info(&mut self, token_payment_info: TokenPaymentInfo) { + self.token_payment_info = Some(token_payment_info); + } + + fn clear_token_payment_info(&mut self) { + self.token_payment_info = None; + } +} + +impl DocumentBaseTransitionV0Methods for DocumentBaseTransitionV1 { + fn id(&self) -> Identifier { + self.id + } + + fn set_id(&mut self, id: Identifier) { + self.id = id; + } + + fn document_type_name(&self) -> &String { + &self.document_type_name + } + + fn document_type_name_owned(self) -> String { + self.document_type_name + } + + fn set_document_type_name(&mut self, document_type_name: String) { + self.document_type_name = document_type_name; + } + + fn data_contract_id(&self) -> Identifier { + self.data_contract_id + } + + fn data_contract_id_ref(&self) -> &Identifier { + &self.data_contract_id + } + + fn set_data_contract_id(&mut self, data_contract_id: Identifier) { + self.data_contract_id = data_contract_id; + } + + fn identity_contract_nonce(&self) -> IdentityNonce { + self.identity_contract_nonce + } + + fn set_identity_contract_nonce(&mut self, identity_contract_nonce: IdentityNonce) { + self.identity_contract_nonce = identity_contract_nonce; + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs new file mode 100644 index 00000000000..3b5edbc24b0 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs @@ -0,0 +1,33 @@ +use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use crate::state_transition::batch_transition::document_base_transition::v1::v1_methods::DocumentBaseTransitionV1Methods; +use crate::tokens::token_payment_info::TokenPaymentInfo; + +impl DocumentBaseTransitionV1Methods for DocumentBaseTransition { + fn token_payment_info(&self) -> Option { + match self { + DocumentBaseTransition::V0(_) => None, + DocumentBaseTransition::V1(v1) => v1.token_payment_info, + } + } + + fn token_payment_info_ref(&self) -> &Option { + match self { + DocumentBaseTransition::V0(_) => &None, + DocumentBaseTransition::V1(v1) => v1.token_payment_info_ref(), + } + } + + fn set_token_payment_info(&mut self, token_payment_info: TokenPaymentInfo) { + match self { + DocumentBaseTransition::V0(_) => { }, + DocumentBaseTransition::V1(v1) => v1.set_token_payment_info(token_payment_info), + } + } + + fn clear_token_payment_info(&mut self) { + match self { + DocumentBaseTransition::V0(_) => { }, + DocumentBaseTransition::V1(v1) => v1.clear_token_payment_info(), + } + } +} \ No newline at end of file diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs index b1d5a81ed0e..800ab5d6c54 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs @@ -31,12 +31,16 @@ use crate::state_transition::data_contract_update_transition::IDENTIFIER_FIELDS; ))] use crate::ProtocolError; #[cfg(any( - feature = "state-transition-json-conversion", - feature = "state-transition-value-conversion" + feature = "state-transition-json-conversion" ))] use platform_value::btreemap_extensions::{ - BTreeValueMapHelper, BTreeValueMapReplacementPathHelper, BTreeValueRemoveFromMapHelper, + BTreeValueMapHelper, BTreeValueMapReplacementPathHelper, }; +#[cfg(any( + feature = "state-transition-json-conversion", + feature = "state-transition-value-conversion" +))] +use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; #[cfg(feature = "state-transition-json-conversion")] use platform_value::ReplacementType; #[cfg(any( diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs index 14b5313cf1e..5d23d2f16c9 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs @@ -24,6 +24,7 @@ use crate::data_contract::document_type::methods::DocumentTypeBasicMethods; use crate::data_contract::document_type::DocumentTypeRef; use crate::document::{Document, DocumentV0}; use crate::fee::Credits; +#[cfg(feature = "state-transition-value-conversion")] use crate::state_transition::batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; #[cfg(feature = "state-transition-value-conversion")] use crate::state_transition::batch_transition::document_base_transition::v0::DocumentTransitionObjectLike; @@ -35,6 +36,7 @@ use platform_version::version::PlatformVersion; #[cfg(feature = "state-transition-value-conversion")] use crate::state_transition::batch_transition; +use crate::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; mod property_names { pub const ENTROPY: &str = "$entropy"; @@ -195,10 +197,6 @@ impl DocumentFromCreateTransitionV0 for Document { { let DocumentCreateTransitionV0 { base, data, .. } = v0; - match base { - DocumentBaseTransition::V0(base_v0) => { - let DocumentBaseTransitionV0 { id, .. } = base_v0; - let requires_created_at = document_type .required_fields() .contains(document::property_names::CREATED_AT); @@ -259,7 +257,7 @@ impl DocumentFromCreateTransitionV0 for Document { .document_structure_version { 0 => Ok(DocumentV0 { - id, + id: base.id(), owner_id, properties: data, revision: document_type.initial_revision(), @@ -280,8 +278,6 @@ impl DocumentFromCreateTransitionV0 for Document { received: version, }), } - } - } } fn try_from_create_transition_v0( @@ -296,10 +292,6 @@ impl DocumentFromCreateTransitionV0 for Document { { let DocumentCreateTransitionV0 { base, data, .. } = v0; - match base { - DocumentBaseTransition::V0(base_v0) => { - let DocumentBaseTransitionV0 { id, .. } = base_v0; - let requires_created_at = document_type .required_fields() .contains(document::property_names::CREATED_AT); @@ -360,7 +352,7 @@ impl DocumentFromCreateTransitionV0 for Document { .document_structure_version { 0 => Ok(DocumentV0 { - id: *id, + id: base.id(), owner_id, properties: data.clone(), revision: document_type.initial_revision(), @@ -381,8 +373,6 @@ impl DocumentFromCreateTransitionV0 for Document { received: version, }), } - } - } } } diff --git a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs new file mode 100644 index 00000000000..aa5c976f291 --- /dev/null +++ b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs @@ -0,0 +1,19 @@ +use bincode_derive::{Decode, Encode}; +use derive_more::Display; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] +#[cfg_attr( + feature = "state-transition-serde-conversion", + derive(Serialize, Deserialize) +)] +pub enum GasFeesPaidBy { + /// The user pays the gas fees + #[default] + DocumentOwner, + /// The contract owner pays the gas fees + ContractOwner, + /// The user is stating his willingness to pay the gas fee if the Contract owner's balance is + /// insufficient. + PreferContractOwner, +} \ No newline at end of file diff --git a/packages/rs-dpp/src/tokens/mod.rs b/packages/rs-dpp/src/tokens/mod.rs index 7ef624e086f..71d9fda092f 100644 --- a/packages/rs-dpp/src/tokens/mod.rs +++ b/packages/rs-dpp/src/tokens/mod.rs @@ -10,6 +10,8 @@ pub mod errors; pub mod info; pub mod status; pub mod token_event; +pub mod token_payment_info; +pub mod gas_fees_paid_by; pub const MAX_TOKEN_NOTE_LEN: usize = 2048; pub type SharedEncryptedNote = (SenderKeyIndex, RecipientKeyIndex, Vec); diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs new file mode 100644 index 00000000000..271e803671f --- /dev/null +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -0,0 +1,116 @@ +use std::collections::BTreeMap; +use bincode_derive::{Decode, Encode}; +use derive_more::{Display, From}; +use serde::{Deserialize, Serialize}; +use platform_value::{Identifier, Value}; +use platform_value::btreemap_extensions::BTreeValueMapHelper; +use crate::balances::credits::TokenAmount; +use crate::data_contract::TokenContractPosition; +use crate::ProtocolError; +use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use crate::tokens::token_payment_info::v0::TokenPaymentInfoV0; +use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; + +pub mod v0; + +#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Display, From)] +#[cfg_attr( + feature = "state-transition-serde-conversion", + derive(Serialize, Deserialize), +)] +pub enum TokenPaymentInfo { + #[display("V0({})", "_0")] + V0(TokenPaymentInfoV0) +} + +impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfo { + // Getters + fn payment_token_contract_id(&self) -> Option { + match self { + TokenPaymentInfo::V0(v0) => v0.payment_token_contract_id(), + } + } + + fn payment_token_contract_id_ref(&self) -> &Option { + match self { + TokenPaymentInfo::V0(v0) => v0.payment_token_contract_id_ref(), + } + } + + fn token_contract_position(&self) -> TokenContractPosition { + match self { + TokenPaymentInfo::V0(v0) => v0.token_contract_position(), + } + } + + fn minimum_token_cost(&self) -> Option { + match self { + TokenPaymentInfo::V0(v0) => v0.minimum_token_cost(), + } + } + + fn maximum_token_cost(&self) -> Option { + match self { + TokenPaymentInfo::V0(v0) => v0.maximum_token_cost(), + } + } + + // Setters + fn set_payment_token_contract_id(&mut self, id: Option) { + match self { + TokenPaymentInfo::V0(v0) => v0.set_payment_token_contract_id(id), + } + } + + fn set_token_contract_position(&mut self, position: TokenContractPosition) { + match self { + TokenPaymentInfo::V0(v0) => v0.set_token_contract_position(position), + } + } + + fn set_minimum_token_cost(&mut self, cost: Option) { + match self { + TokenPaymentInfo::V0(v0) => v0.set_minimum_token_cost(cost), + } + } + + fn set_maximum_token_cost(&mut self, cost: Option) { + match self { + TokenPaymentInfo::V0(v0) => v0.set_maximum_token_cost(cost), + } + } + + fn gas_fees_paid_by(&self) -> GasFeesPaidBy { + match self { + TokenPaymentInfo::V0(v0) => v0.gas_fees_paid_by(), + } + } + + fn set_gas_fees_paid_by(&mut self, payer: GasFeesPaidBy) { + match self { + TokenPaymentInfo::V0(v0) => v0.set_gas_fees_paid_by(payer), + } + } +} + +impl TryFrom> for TokenPaymentInfo { + type Error = ProtocolError; + + fn try_from(map: BTreeMap) -> Result { + let format_version = map.get_str("$format_version")?; + match format_version { + "0" => { + let token_payment_info: TokenPaymentInfoV0 = map.try_into()?; + + Ok(token_payment_info.into()) + } + version => Err(ProtocolError::UnknownVersionMismatch { + method: "TokenPaymentInfo::from_value".to_string(), + known_versions: vec![0], + received: version + .parse() + .map_err(|_| ProtocolError::Generic("Conversion error".to_string()))?, + }), + } + } +} \ No newline at end of file diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs new file mode 100644 index 00000000000..443add66591 --- /dev/null +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs @@ -0,0 +1,125 @@ +pub mod v0_accessors; + +use std::collections::BTreeMap; +use bincode_derive::{Decode, Encode}; +use derive_more::Display; +use serde::{Deserialize, Serialize}; +use platform_value::{Identifier, Value}; +use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; +use crate::balances::credits::TokenAmount; +use crate::data_contract::TokenContractPosition; +use crate::ProtocolError; +use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; + +#[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] +#[cfg_attr( + feature = "state-transition-serde-conversion", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] +#[display( + "Contract ID: {:?}, Token Position: {:?}, Min Cost: {:?}, Max Cost: {:?}, Gas Fees Paid By: {}", + payment_token_contract_id, + token_contract_position, + minimum_token_cost, + maximum_token_cost, + gas_fees_paid_by, +)] +pub struct TokenPaymentInfoV0 { + /// By default, we use a token in the same contract, this field must be set if the document + /// requires payment using another contracts token. + pub payment_token_contract_id: Option, + /// If we are expecting to pay with a token in a contract, which token are we expecting + /// to pay with? + /// We have this set so contract owners can't switch out to more valuable token. + /// For example if my Data contract + pub token_contract_position: TokenContractPosition, + /// Minimum token cost, this most often should not be set + pub minimum_token_cost: Option, + /// Maximum token cost, this most often should be set + /// If: + /// - a client does not have this set + /// - and the data contract allows the price of NFTs to be changed by the data contract's owner or allowed party. + /// Then: + /// - The user could see the cost changed on them + pub maximum_token_cost: Option, + /// Who pays the gas fees, this needs to match what the contract allows + pub gas_fees_paid_by: GasFeesPaidBy +} + +impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfoV0 { + // Getters + fn payment_token_contract_id(&self) -> Option { + self.payment_token_contract_id + } + + fn payment_token_contract_id_ref(&self) -> &Option { + &self.payment_token_contract_id + } + + fn token_contract_position(&self) -> TokenContractPosition { + self.token_contract_position + } + + fn minimum_token_cost(&self) -> Option { + self.minimum_token_cost + } + + fn maximum_token_cost(&self) -> Option { + self.maximum_token_cost + } + + // Setters + fn set_payment_token_contract_id(&mut self, id: Option) { + self.payment_token_contract_id = id; + } + + fn set_token_contract_position(&mut self, position: TokenContractPosition) { + self.token_contract_position = position; + } + + fn set_minimum_token_cost(&mut self, cost: Option) { + self.minimum_token_cost = cost; + } + + fn set_maximum_token_cost(&mut self, cost: Option) { + self.maximum_token_cost = cost; + } + + fn gas_fees_paid_by(&self) -> GasFeesPaidBy { + self.gas_fees_paid_by + } + + fn set_gas_fees_paid_by(&mut self, payer: GasFeesPaidBy) { + self.gas_fees_paid_by = payer; + } +} + +impl TryFrom> for TokenPaymentInfoV0 { + type Error = ProtocolError; + + fn try_from(mut map: BTreeMap) -> Result { + Ok(TokenPaymentInfoV0 { + payment_token_contract_id: map.remove_optional_identifier("paymentTokenContractId")?, + + token_contract_position: map + .remove_optional_integer("tokenContractPosition")? + .unwrap_or_default(), + + minimum_token_cost: map.remove_optional_integer("minimumTokenCost")?, + + maximum_token_cost: map.remove_optional_integer("maximumTokenCost")?, + + gas_fees_paid_by: map + .remove_optional_string("gasFeesPaidBy")? + .map(|v| match v.as_str() { + "DocumentOwner" => GasFeesPaidBy::DocumentOwner, + "ContractOwner" => GasFeesPaidBy::ContractOwner, + "PreferContractOwner" => GasFeesPaidBy::PreferContractOwner, + _ => GasFeesPaidBy::default(), + }) + .unwrap_or_default(), + }) + } +} \ No newline at end of file diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs new file mode 100644 index 00000000000..02324306df3 --- /dev/null +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs @@ -0,0 +1,42 @@ +use platform_value::Identifier; +use crate::balances::credits::TokenAmount; +use crate::data_contract::TokenContractPosition; +use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; + +/// Trait providing accessor and mutator methods for `TokenPaymentInfoV0`. +pub trait TokenPaymentInfoAccessorsV0 { + /// Returns a cloned copy of the `payment_token_contract_id` field. + fn payment_token_contract_id(&self) -> Option; + + /// Returns a reference to the `payment_token_contract_id` field. + /// + /// This method avoids copying and can be used when only read access is needed. + fn payment_token_contract_id_ref(&self) -> &Option; + + /// Returns the `token_contract_position` field. + fn token_contract_position(&self) -> TokenContractPosition; + + /// Returns a copy of the `minimum_token_cost` field. + fn minimum_token_cost(&self) -> Option; + + /// Returns a copy of the `maximum_token_cost` field. + fn maximum_token_cost(&self) -> Option; + + /// Sets the `payment_token_contract_id` field to the given value. + fn set_payment_token_contract_id(&mut self, id: Option); + + /// Sets the `token_contract_position` field to the given value. + fn set_token_contract_position(&mut self, position: TokenContractPosition); + + /// Sets the `minimum_token_cost` field to the given value. + fn set_minimum_token_cost(&mut self, cost: Option); + + /// Sets the `maximum_token_cost` field to the given value. + fn set_maximum_token_cost(&mut self, cost: Option); + + /// Returns the `gas_fees_paid_by` strategy. + fn gas_fees_paid_by(&self) -> GasFeesPaidBy; + + /// Sets the `gas_fees_paid_by` strategy. + fn set_gas_fees_paid_by(&mut self, payer: GasFeesPaidBy); +} \ No newline at end of file diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs index 5b82d840181..7f97d3a8f4b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs @@ -30,7 +30,6 @@ use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; -use drive::state_transition_action::system::bump_identity_nonce_action::BumpIdentityNonceAction; use drive::state_transition_action::StateTransitionAction; pub(in crate::execution::validation::state_transition::state_transitions::data_contract_update) trait DataContractUpdateStateTransitionStateValidationV0 { diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs index cbd1b23c2c5..075693c6700 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs @@ -15,16 +15,12 @@ impl DocumentBaseTransitionAction { get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, ) -> Result { - match value { - DocumentBaseTransition::V0(v0) => Ok( - DocumentBaseTransitionActionV0::try_from_base_transition_with_contract_lookup( - v0, - get_data_contract, - get_token_cost, - )? - .into(), - ), - } + Ok(DocumentBaseTransitionActionV0::try_from_base_transition_with_contract_lookup( + value, + get_data_contract, + get_token_cost, + )? + .into()) } /// from borrowed base transition with contract lookup @@ -33,8 +29,11 @@ impl DocumentBaseTransitionAction { get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, ) -> Result { - match value { - DocumentBaseTransition::V0(v0) => Ok(DocumentBaseTransitionActionV0::try_from_borrowed_base_transition_with_contract_lookup(v0, get_data_contract, get_token_cost)?.into()), - } + Ok(DocumentBaseTransitionActionV0::try_from_borrowed_base_transition_with_contract_lookup( + value, + get_data_contract, + get_token_cost, + )? + .into()) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs index 5f51a3030fa..7e252310a96 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs @@ -7,13 +7,13 @@ use dpp::identifier::Identifier; use dpp::prelude::IdentityNonce; use dpp::ProtocolError; use std::sync::Arc; - +use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; use crate::drive::contract::DataContractFetchInfo; #[derive(Debug, Clone)] /// document base transition action v0 pub struct DocumentBaseTransitionActionV0 { - /// The document Id + /// The document ID pub id: Identifier, /// The identity contract nonce, this is used to stop replay attacks pub identity_contract_nonce: IdentityNonce, @@ -23,11 +23,13 @@ pub struct DocumentBaseTransitionActionV0 { pub data_contract: Arc, /// Token cost with the token_id coming first pub token_cost: Option<(Identifier, TokenAmount)>, + /// Who pays the gas fees + pub gas_fees_paid_by: GasFeesPaidBy, } /// document base transition action accessors v0 pub trait DocumentBaseTransitionActionAccessorsV0 { - /// The document Id + /// The document ID fn id(&self) -> Identifier; /// The document type diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs index 05dc364dd99..fb30f148711 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs @@ -6,28 +6,27 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::ProtocolError; -use dpp::state_transition::batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; +use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use dpp::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; +use dpp::state_transition::batch_transition::document_base_transition::v1::v1_methods::DocumentBaseTransitionV1Methods; use dpp::tokens::calculate_token_id; +use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; +use dpp::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; use crate::drive::contract::DataContractFetchInfo; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionV0; impl DocumentBaseTransitionActionV0 { /// try from base transition with contract lookup pub fn try_from_base_transition_with_contract_lookup( - value: DocumentBaseTransitionV0, + value: DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, ) -> Result { - let DocumentBaseTransitionV0 { - id, - document_type_name, - data_contract_id, - identity_contract_nonce, - } = value; + let data_contract_id = value.data_contract_id(); let data_contract = get_data_contract(data_contract_id)?; let document_type = data_contract .contract - .document_type_borrowed_for_name(document_type_name.as_str())?; + .document_type_borrowed_for_name(value.document_type_name().as_str())?; let token_cost = get_token_cost(document_type).map(|(token_contract_position, token_amount)| { ( @@ -35,31 +34,28 @@ impl DocumentBaseTransitionActionV0 { token_amount, ) }); + let gas_fees_paid_by = value.token_payment_info_ref().as_ref().map(|token_payment_info| token_payment_info.gas_fees_paid_by()).unwrap_or(GasFeesPaidBy::DocumentOwner); Ok(DocumentBaseTransitionActionV0 { - id, - identity_contract_nonce, - document_type_name, + id: value.id(), + identity_contract_nonce: value.identity_contract_nonce(), + document_type_name: value.document_type_name_owned(), data_contract, token_cost, + gas_fees_paid_by, }) } /// try from borrowed base transition with contract lookup pub fn try_from_borrowed_base_transition_with_contract_lookup( - value: &DocumentBaseTransitionV0, + value: &DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, ) -> Result { - let DocumentBaseTransitionV0 { - id, - document_type_name, - data_contract_id, - identity_contract_nonce, - } = value; - let data_contract = get_data_contract(*data_contract_id)?; + let data_contract_id = value.data_contract_id(); + let data_contract = get_data_contract(data_contract_id)?; let document_type = data_contract .contract - .document_type_borrowed_for_name(document_type_name)?; + .document_type_borrowed_for_name(value.document_type_name().as_str())?; let token_cost = get_token_cost(document_type).map(|(token_contract_position, token_amount)| { ( @@ -67,12 +63,14 @@ impl DocumentBaseTransitionActionV0 { token_amount, ) }); + let gas_fees_paid_by = value.token_payment_info_ref().as_ref().map(|token_payment_info| token_payment_info.gas_fees_paid_by()).unwrap_or(GasFeesPaidBy::DocumentOwner); Ok(DocumentBaseTransitionActionV0 { - id: *id, - identity_contract_nonce: *identity_contract_nonce, - document_type_name: document_type_name.clone(), + id: value.id(), + identity_contract_nonce: value.identity_contract_nonce(), + document_type_name: value.document_type_name().clone(), data_contract, token_cost, + gas_fees_paid_by, }) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/mod.rs index 538b232faad..12e4da46ce8 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/mod.rs @@ -29,7 +29,6 @@ use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; use dpp::data_contract::associated_token::token_keeps_history_rules::accessors::v0::TokenKeepsHistoryRulesV0Getters; use dpp::data_contract::document_type::DocumentTypeRef; -use dpp::data_contracts::SystemDataContract; use dpp::document::Document; use dpp::identifier::Identifier; use dpp::prelude::{DataContract, IdentityNonce}; diff --git a/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs b/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs index e0691b16e68..db6281a1ede 100644 --- a/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs @@ -101,16 +101,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - DocumentBaseTransition::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_document_base_transition( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_document_base_transition( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from borrowed base transition @@ -119,16 +115,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - DocumentBaseTransition::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_borrowed_document_base_transition( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_borrowed_document_base_transition( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from base transition @@ -137,16 +129,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - DocumentBaseTransitionAction::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_document_base_transition_action( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_document_base_transition_action( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from borrowed base transition @@ -155,16 +143,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - DocumentBaseTransitionAction::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_borrowed_document_base_transition_action( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_borrowed_document_base_transition_action( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from base transition @@ -173,16 +157,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - TokenBaseTransition::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_token_base_transition( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_token_base_transition( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from borrowed base transition @@ -191,16 +171,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - TokenBaseTransition::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_borrowed_token_base_transition( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_borrowed_token_base_transition( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from base transition @@ -209,16 +185,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - TokenBaseTransitionAction::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_token_base_transition_action( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_token_base_transition_action( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from borrowed base transition @@ -227,16 +199,12 @@ impl BumpIdentityDataContractNonceAction { identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - match value { - TokenBaseTransitionAction::V0(v0) => { - BumpIdentityDataContractNonceActionV0::from_borrowed_token_base_transition_action( - v0, - identity_id, - user_fee_increase, - ) - .into() - } - } + BumpIdentityDataContractNonceActionV0::from_borrowed_token_base_transition_action( + value, + identity_id, + user_fee_increase, + ) + .into() } /// from data contract update diff --git a/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/v0/transformer.rs index c87a865a70c..d9b2bf74e96 100644 --- a/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/v0/transformer.rs @@ -1,164 +1,125 @@ use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::platform_value::Identifier; use dpp::prelude::UserFeeIncrease; - +use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use dpp::state_transition::data_contract_update_transition::DataContractUpdateTransitionV0; -use dpp::state_transition::batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; -use dpp::state_transition::batch_transition::token_base_transition::v0::TokenBaseTransitionV0; +use dpp::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; +use dpp::state_transition::batch_transition::token_base_transition::TokenBaseTransition; +use dpp::state_transition::batch_transition::token_base_transition::v0::v0_methods::TokenBaseTransitionV0Methods; use crate::state_transition_action::contract::data_contract_update::v0::DataContractUpdateTransitionActionV0; -use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionV0; -use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::TokenBaseTransitionActionV0; +use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; +use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::{TokenBaseTransitionAction, TokenBaseTransitionActionAccessorsV0}; use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceActionV0; impl BumpIdentityDataContractNonceActionV0 { /// from base transition pub fn from_document_base_transition( - value: DocumentBaseTransitionV0, + value: DocumentBaseTransition, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let DocumentBaseTransitionV0 { - data_contract_id, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id, - identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from borrowed base transition pub fn from_borrowed_document_base_transition( - value: &DocumentBaseTransitionV0, + value: &DocumentBaseTransition, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let DocumentBaseTransitionV0 { - data_contract_id, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id: *data_contract_id, - identity_contract_nonce: *identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from base transition pub fn from_document_base_transition_action( - value: DocumentBaseTransitionActionV0, + value: DocumentBaseTransitionAction, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let DocumentBaseTransitionActionV0 { - data_contract, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id: data_contract.contract.id(), - identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from borrowed base transition pub fn from_borrowed_document_base_transition_action( - value: &DocumentBaseTransitionActionV0, + value: &DocumentBaseTransitionAction, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let DocumentBaseTransitionActionV0 { - data_contract, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id: data_contract.contract.id(), - identity_contract_nonce: *identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from base transition pub fn from_token_base_transition( - value: TokenBaseTransitionV0, + value: TokenBaseTransition, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let TokenBaseTransitionV0 { - data_contract_id, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id, - identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from borrowed base transition pub fn from_borrowed_token_base_transition( - value: &TokenBaseTransitionV0, + value: &TokenBaseTransition, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let TokenBaseTransitionV0 { - data_contract_id, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id: *data_contract_id, - identity_contract_nonce: *identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from base transition pub fn from_token_base_transition_action( - value: TokenBaseTransitionActionV0, + value: TokenBaseTransitionAction, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let TokenBaseTransitionActionV0 { - data_contract, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id: data_contract.contract.id(), - identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } /// from borrowed base transition pub fn from_borrowed_token_base_transition_action( - value: &TokenBaseTransitionActionV0, + value: &TokenBaseTransitionAction, identity_id: Identifier, user_fee_increase: UserFeeIncrease, ) -> Self { - let TokenBaseTransitionActionV0 { - data_contract, - identity_contract_nonce, - .. - } = value; BumpIdentityDataContractNonceActionV0 { identity_id, - data_contract_id: data_contract.contract.id(), - identity_contract_nonce: *identity_contract_nonce, + data_contract_id: value.data_contract_id(), + identity_contract_nonce: value.identity_contract_nonce(), user_fee_increase, } } diff --git a/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs b/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs index 8b2b2daa250..89389fa3cb3 100644 --- a/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs +++ b/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs @@ -59,6 +59,17 @@ pub trait BTreeValueRemoveFromMapHelper { where K: TryFrom + Ord, V: TryFrom; + + fn remove_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result, Error> + where + K: TryFrom + Ord; + + fn remove_optional_map_as_btree_map_keep_values_as_platform_value( + &mut self, + key: &str, + ) -> Result>, Error> + where + K: TryFrom + Ord; } pub trait BTreeValueRemoveTupleFromMapHelper { @@ -341,6 +352,37 @@ impl BTreeValueRemoveFromMapHelper for BTreeMap { }) .transpose() } + + fn remove_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result, Error> + where + K: TryFrom + Ord + { + self.remove_optional_map_as_btree_map_keep_values_as_platform_value(key)? + .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}"))) + } + + fn remove_optional_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result>, Error> + where + K: TryFrom + Ord + { + self.remove(key) + .and_then(|v| { + if v.is_null() { + None + } else if let Value::Map(map) = v { + Some( + map.iter() + .map(|(key, value)| { + Ok((key.clone().try_into()?, value.clone())) + }) + .collect(), + ) + } else { + None + } + }) + .transpose() + } } impl BTreeValueRemoveFromMapHelper for BTreeMap { @@ -621,6 +663,38 @@ impl BTreeValueRemoveFromMapHelper for BTreeMap { }) .transpose() } + + fn remove_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result, Error> + where + K: TryFrom + Ord, + { + self.remove_optional_map_as_btree_map_keep_values_as_platform_value(key)? + .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}"))) + } + + fn remove_optional_map_as_btree_map_keep_values_as_platform_value( + &mut self, + key: &str, + ) -> Result>, Error> + where + K: TryFrom + Ord, + { + self.remove(key) + .and_then(|v| { + if v.is_null() { + None + } else if let Value::Map(map) = v { + Some( + map.into_iter() + .map(|(key, value)| Ok((key.try_into()?, value))) + .collect(), + ) + } else { + None + } + }) + .transpose() + } } impl BTreeValueRemoveTupleFromMapHelper for BTreeMap { From eda295f91466c00ad3982234b7a40e62c1c6fa69 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 27 Mar 2025 12:12:30 +0700 Subject: [PATCH 02/18] basic functionality --- .../document_type/accessors/mod.rs | 92 +++-- .../document_type/accessors/v0/mod.rs | 5 + .../document_type/accessors/v1/mod.rs | 66 +++- .../class_methods/try_from_schema/v1/mod.rs | 41 ++- .../document_type/token_costs/accessors.rs | 45 +-- .../document_type/token_costs/mod.rs | 45 +-- .../document_type/token_costs/v0/mod.rs | 69 ++-- .../document_type/v0/accessors.rs | 8 +- .../src/data_contract/document_type/v0/mod.rs | 7 - .../document_type/v1/accessors.rs | 23 +- .../src/data_contract/document_type/v1/mod.rs | 34 +- .../src/document/document_factory/mod.rs | 8 +- .../src/document/document_factory/v0/mod.rs | 41 ++- .../specialized_document_factory/mod.rs | 8 +- .../specialized_document_factory/v0/mod.rs | 39 ++- .../src/errors/consensus/basic/basic_error.rs | 7 +- .../consensus/basic/data_contract/mod.rs | 2 + .../unknown_gas_fees_paid_by_error.rs | 46 +++ packages/rs-dpp/src/errors/consensus/codes.rs | 1 + .../document_base_transition/from_document.rs | 10 + .../document_base_transition/mod.rs | 2 +- .../document_base_transition/v0/mod.rs | 7 +- .../v1/from_document.rs | 4 +- .../document_base_transition/v1/mod.rs | 36 +- .../document_base_transition/v1/v1_methods.rs | 6 +- .../document_base_transition/v1_methods.rs | 8 +- .../document_create_transition/convertible.rs | 10 +- .../from_document.rs | 3 + .../v0/from_document.rs | 3 + .../document_create_transition/v0/mod.rs | 324 +++++++++--------- .../from_document.rs | 3 + .../v0/from_document.rs | 3 + .../from_document.rs | 3 + .../v0/from_document.rs | 3 + .../from_document.rs | 3 + .../v0/from_document.rs | 3 + .../from_document.rs | 3 + .../v0/from_document.rs | 3 + .../from_document.rs | 3 + .../v0/from_document.rs | 3 + .../document/batch_transition/methods/mod.rs | 19 + .../batch_transition/methods/v0/mod.rs | 7 + .../batch_transition/v0/v0_methods.rs | 13 + .../batch_transition/v1/v0_methods.rs | 13 + .../get_document_transitions_fixture.rs | 9 +- .../rs-dpp/src/tokens/gas_fees_paid_by.rs | 57 ++- packages/rs-dpp/src/tokens/mod.rs | 3 +- .../tokens/token_amount_on_contract_token.rs | 16 + .../src/tokens/token_payment_info/mod.rs | 22 +- .../src/tokens/token_payment_info/v0/mod.rs | 22 +- .../token_payment_info/v0/v0_accessors.rs | 4 +- .../src/execution/check_tx/v0/mod.rs | 2 + .../block_processing_end_events/tests.rs | 8 + .../data_triggers/triggers/dashpay/v0/mod.rs | 21 +- .../data_triggers/triggers/dpns/v0/mod.rs | 2 +- .../triggers/withdrawals/v0/mod.rs | 3 + .../batch/tests/document/creation.rs | 213 +++++++++++- .../batch/tests/document/deletion.rs | 19 +- .../batch/tests/document/dpns.rs | 12 + .../batch/tests/document/mod.rs | 2 +- .../batch/tests/document/nft.rs | 34 +- .../batch/tests/document/replacement.rs | 25 +- .../batch/tests/document/transfer.rs | 14 +- .../state_transition/state_transitions/mod.rs | 63 +++- ...rypto-card-game-use-external-currency.json | 137 ++++++++ .../transformer.rs | 35 +- .../document_base_transition_action/v0/mod.rs | 4 +- .../v0/transformer.rs | 55 ++- .../transformer.rs | 16 +- .../btreemap_removal_extensions.rs | 30 +- .../v2.rs | 2 +- .../src/platform/transition/put_document.rs | 1 + 72 files changed, 1400 insertions(+), 513 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_gas_fees_paid_by_error.rs create mode 100644 packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs create mode 100644 packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json diff --git a/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs b/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs index 49facffa179..38304118251 100644 --- a/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs @@ -8,20 +8,28 @@ use crate::data_contract::document_type::{DocumentType, DocumentTypeMutRef, Docu use platform_value::{Identifier, Value}; -use crate::balances::credits::TokenAmount; use crate::data_contract::document_type::restricted_creation::CreationRestrictionMode; #[cfg(feature = "validation")] use crate::data_contract::document_type::validator::StatelessJsonSchemaLazyValidator; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; -use crate::data_contract::TokenContractPosition; use crate::document::transfer::Transferable; use crate::identity::SecurityLevel; use crate::nft::TradeMode; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use indexmap::IndexMap; use std::collections::{BTreeMap, BTreeSet}; pub use v0::*; pub use v1::*; +impl DocumentTypeV0MutGetters for DocumentType { + fn schema_mut(&mut self) -> &mut Value { + match self { + DocumentType::V0(v0) => v0.schema_mut(), + DocumentType::V1(v1) => v1.schema_mut(), + } + } +} + impl DocumentTypeV0Getters for DocumentType { fn name(&self) -> &String { match self { @@ -195,6 +203,50 @@ impl DocumentTypeV0Setters for DocumentType { } } +impl DocumentTypeV1Setters for DocumentType { + fn set_document_creation_token_cost(&mut self, cost: Option) { + match self { + DocumentType::V0(_) => { /* no-op */ } + DocumentType::V1(v1) => v1.set_document_creation_token_cost(cost), + } + } + + fn set_document_replacement_token_cost(&mut self, cost: Option) { + match self { + DocumentType::V0(_) => { /* no-op */ } + DocumentType::V1(v1) => v1.set_document_replacement_token_cost(cost), + } + } + + fn set_document_deletion_token_cost(&mut self, cost: Option) { + match self { + DocumentType::V0(_) => { /* no-op */ } + DocumentType::V1(v1) => v1.set_document_deletion_token_cost(cost), + } + } + + fn set_document_transfer_token_cost(&mut self, cost: Option) { + match self { + DocumentType::V0(_) => { /* no-op */ } + DocumentType::V1(v1) => v1.set_document_transfer_token_cost(cost), + } + } + + fn set_document_price_update_token_cost(&mut self, cost: Option) { + match self { + DocumentType::V0(_) => { /* no-op */ } + DocumentType::V1(v1) => v1.set_document_price_update_token_cost(cost), + } + } + + fn set_document_purchase_token_cost(&mut self, cost: Option) { + match self { + DocumentType::V0(_) => { /* no-op */ } + DocumentType::V1(v1) => v1.set_document_purchase_token_cost(cost), + } + } +} + impl<'a> DocumentTypeV0Getters for DocumentTypeRef<'a> { fn name(&self) -> &String { match self { @@ -532,42 +584,42 @@ impl<'a> DocumentTypeV0Setters for DocumentTypeMutRef<'a> { } impl DocumentTypeV1Getters for DocumentType { - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_creation_token_cost(&self) -> Option { match self { DocumentType::V0(_) => None, DocumentType::V1(v1) => v1.document_creation_token_cost(), } } - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_replacement_token_cost(&self) -> Option { match self { DocumentType::V0(_) => None, DocumentType::V1(v1) => v1.document_replacement_token_cost(), } } - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_deletion_token_cost(&self) -> Option { match self { DocumentType::V0(_) => None, DocumentType::V1(v1) => v1.document_deletion_token_cost(), } } - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_transfer_token_cost(&self) -> Option { match self { DocumentType::V0(_) => None, DocumentType::V1(v1) => v1.document_transfer_token_cost(), } } - fn document_update_price_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_update_price_token_cost(&self) -> Option { match self { DocumentType::V0(_) => None, DocumentType::V1(v1) => v1.document_update_price_token_cost(), } } - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_purchase_token_cost(&self) -> Option { match self { DocumentType::V0(_) => None, DocumentType::V1(v1) => v1.document_purchase_token_cost(), @@ -576,42 +628,42 @@ impl DocumentTypeV1Getters for DocumentType { } impl<'a> DocumentTypeV1Getters for DocumentTypeRef<'a> { - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_creation_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_creation_token_cost(), } } - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_replacement_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_replacement_token_cost(), } } - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_deletion_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_deletion_token_cost(), } } - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_transfer_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_transfer_token_cost(), } } - fn document_update_price_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_update_price_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_update_price_token_cost(), } } - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_purchase_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_purchase_token_cost(), @@ -620,42 +672,42 @@ impl<'a> DocumentTypeV1Getters for DocumentTypeRef<'a> { } impl<'a> DocumentTypeV1Getters for DocumentTypeMutRef<'a> { - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_creation_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_creation_token_cost(), } } - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_replacement_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_replacement_token_cost(), } } - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_deletion_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_deletion_token_cost(), } } - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_transfer_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_transfer_token_cost(), } } - fn document_update_price_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_update_price_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_update_price_token_cost(), } } - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_purchase_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_purchase_token_cost(), diff --git a/packages/rs-dpp/src/data_contract/document_type/accessors/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/accessors/v0/mod.rs index 5769860f1ae..7aa1da24bfe 100644 --- a/packages/rs-dpp/src/data_contract/document_type/accessors/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/accessors/v0/mod.rs @@ -14,6 +14,11 @@ use crate::nft::TradeMode; use indexmap::IndexMap; use std::collections::{BTreeMap, BTreeSet}; +pub trait DocumentTypeV0MutGetters { + /// Gets the schema as mut + fn schema_mut(&mut self) -> &mut Value; +} + pub trait DocumentTypeV0Getters { /// Returns the name of the document type. fn name(&self) -> &String; diff --git a/packages/rs-dpp/src/data_contract/document_type/accessors/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/accessors/v1/mod.rs index c05f3a498b4..d908adec2f5 100644 --- a/packages/rs-dpp/src/data_contract/document_type/accessors/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/accessors/v1/mod.rs @@ -1,47 +1,85 @@ -use crate::balances::credits::TokenAmount; -use crate::data_contract::TokenContractPosition; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; /// Trait providing getters for retrieving token costs associated with different document operations. pub trait DocumentTypeV1Getters { /// Returns the token cost associated with document creation, if applicable. /// /// # Returns - /// - `Some((TokenContractPosition, TokenAmount))` if a creation cost exists. + /// - `Some(TokenActionCost)` if a creation cost exists. /// - `None` if no cost is set for document creation. - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_creation_token_cost(&self) -> Option; /// Returns the token cost associated with document replacement (updating), if applicable. /// /// # Returns - /// - `Some((TokenContractPosition, TokenAmount))` if a replacement cost exists. + /// - `Some(TokenActionCost)` if a replacement cost exists. /// - `None` if no cost is set for document replacement. - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_replacement_token_cost(&self) -> Option; /// Returns the token cost associated with document deletion, if applicable. /// /// # Returns - /// - `Some((TokenContractPosition, TokenAmount))` if a deletion cost exists. + /// - `Some(TokenActionCost)` if a deletion cost exists. /// - `None` if no cost is set for document deletion. - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_deletion_token_cost(&self) -> Option; /// Returns the token cost associated with document transfer, if applicable. /// /// # Returns - /// - `Some((TokenContractPosition, TokenAmount))` if a transfer cost exists. + /// - `Some(TokenActionCost)` if a transfer cost exists. /// - `None` if no cost is set for document transfer. - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_transfer_token_cost(&self) -> Option; /// Returns the token cost associated with updating the price of a document, if applicable. /// /// # Returns - /// - `Some((TokenContractPosition, TokenAmount))` if an update price cost exists. + /// - `Some(TokenActionCost)` if an update price cost exists. /// - `None` if no cost is set for updating the price. - fn document_update_price_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_update_price_token_cost(&self) -> Option; /// Returns the token cost associated with document purchase, if applicable. /// /// # Returns - /// - `Some((TokenContractPosition, TokenAmount))` if a purchase cost exists. + /// - `Some(TokenActionCost)` if a purchase cost exists. /// - `None` if no cost is set for document purchase. - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_purchase_token_cost(&self) -> Option; +} + +/// Trait providing setters for assigning token costs to different document operations. +pub trait DocumentTypeV1Setters { + /// Sets the token cost for document creation. + /// + /// # Arguments + /// - `cost`: `Some(DocumentActionTokenCost)` to set a cost, or `None` to clear it. + fn set_document_creation_token_cost(&mut self, cost: Option); + + /// Sets the token cost for document replacement (updating). + /// + /// # Arguments + /// - `cost`: `Some(DocumentActionTokenCost)` to set a cost, or `None` to clear it. + fn set_document_replacement_token_cost(&mut self, cost: Option); + + /// Sets the token cost for document deletion. + /// + /// # Arguments + /// - `cost`: `Some(DocumentActionTokenCost)` to set a cost, or `None` to clear it. + fn set_document_deletion_token_cost(&mut self, cost: Option); + + /// Sets the token cost for document transfer. + /// + /// # Arguments + /// - `cost`: `Some(DocumentActionTokenCost)` to set a cost, or `None` to clear it. + fn set_document_transfer_token_cost(&mut self, cost: Option); + + /// Sets the token cost for updating the price of a document. + /// + /// # Arguments + /// - `cost`: `Some(DocumentActionTokenCost)` to set a cost, or `None` to clear it. + fn set_document_price_update_token_cost(&mut self, cost: Option); + + /// Sets the token cost for document purchase. + /// + /// # Arguments + /// - `cost`: `Some(DocumentActionTokenCost)` to set a cost, or `None` to clear it. + fn set_document_purchase_token_cost(&mut self, cost: Option); } diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs index 8e503e723c1..6483d209da1 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs @@ -50,6 +50,8 @@ use crate::data_contract::errors::DataContractError; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; use crate::data_contract::TokenContractPosition; use crate::identity::SecurityLevel; +use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; #[cfg(feature = "validation")] use crate::validation::meta_validators::DOCUMENT_META_SCHEMA_V0; use crate::validation::operations::ProtocolValidationOperation; @@ -543,19 +545,34 @@ impl DocumentTypeV1 { let token_costs_value = schema.get_optional_value("tokenCost")?; - let extract_cost = - |key: &str| -> Result, ProtocolError> { - token_costs_value - .and_then(|v| v.get_optional_value(key).transpose()) - .transpose()? - .map(|action_cost| { - Ok(( - action_cost.get_integer::("tokenPosition")?, - action_cost.get_integer::("amount")?, - )) + let extract_cost = |key: &str| -> Result, ProtocolError> { + token_costs_value + .and_then(|v| v.get_optional_value(key).transpose()) + .transpose()? + .map(|action_cost| { + // Extract an optional contract_id. Adjust the key if necessary. + let contract_id = action_cost.get_optional_identifier("contractId")?; + // Extract token_contract_position as an integer, then convert it. + let token_contract_position = + action_cost.get_integer::("tokenPosition")?; + // Extract the token amount. + let token_amount = action_cost.get_integer::("amount")?; + // Extract an optional string and map it to the enum, defaulting if missing or unrecognized. + let gas_fees_paid_by = action_cost + .get_optional_integer::("gasFeesPaidBy")? + .map(|int| int.try_into()) + .transpose()? + .unwrap_or(GasFeesPaidBy::DocumentOwner); + + Ok(DocumentActionTokenCost { + contract_id, + token_contract_position, + token_amount, + gas_fees_paid_by, }) - .transpose() - }; + }) + .transpose() + }; let token_costs = TokenCostsV0 { create: extract_cost("create")?, diff --git a/packages/rs-dpp/src/data_contract/document_type/token_costs/accessors.rs b/packages/rs-dpp/src/data_contract/document_type/token_costs/accessors.rs index 25482cae5ee..4ae870ed0d2 100644 --- a/packages/rs-dpp/src/data_contract/document_type/token_costs/accessors.rs +++ b/packages/rs-dpp/src/data_contract/document_type/token_costs/accessors.rs @@ -1,62 +1,43 @@ -use crate::balances::credits::TokenAmount; -use crate::data_contract::TokenContractPosition; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; /// Trait providing getters for retrieving token costs associated with different operations. pub trait TokenCostGettersV0 { /// Returns the token cost associated with document creation, if applicable. - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_creation_token_cost(&self) -> Option; /// Returns the token cost associated with document replacement (updating), if applicable. - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_replacement_token_cost(&self) -> Option; /// Returns the token cost associated with document deletion, if applicable. - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_deletion_token_cost(&self) -> Option; /// Returns the token cost associated with document transfer, if applicable. - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_transfer_token_cost(&self) -> Option; /// Returns the token cost associated with updating the price of a document, if applicable. - fn document_price_update_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_price_update_token_cost(&self) -> Option; /// Returns the token cost associated with document purchase, if applicable. - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)>; + fn document_purchase_token_cost(&self) -> Option; } /// Trait providing setters for modifying token costs associated with different operations. pub trait TokenCostSettersV0 { /// Sets the token cost for document creation. - fn set_document_creation_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ); + fn set_document_creation_token_cost(&mut self, cost: Option); /// Sets the token cost for document replacement (updating). - fn set_document_replacement_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ); + fn set_document_replacement_token_cost(&mut self, cost: Option); /// Sets the token cost for document deletion. - fn set_document_deletion_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ); + fn set_document_deletion_token_cost(&mut self, cost: Option); /// Sets the token cost for document transfer. - fn set_document_transfer_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ); + fn set_document_transfer_token_cost(&mut self, cost: Option); /// Sets the token cost for updating the price of a document. - fn set_document_price_update_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ); + fn set_document_price_update_token_cost(&mut self, cost: Option); /// Sets the token cost for document purchase. - fn set_document_purchase_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ); + fn set_document_purchase_token_cost(&mut self, cost: Option); } diff --git a/packages/rs-dpp/src/data_contract/document_type/token_costs/mod.rs b/packages/rs-dpp/src/data_contract/document_type/token_costs/mod.rs index 7d1158c3119..70a68a94a9d 100644 --- a/packages/rs-dpp/src/data_contract/document_type/token_costs/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/token_costs/mod.rs @@ -1,9 +1,8 @@ -use crate::balances::credits::TokenAmount; use crate::data_contract::document_type::token_costs::accessors::{ TokenCostGettersV0, TokenCostSettersV0, }; use crate::data_contract::document_type::token_costs::v0::TokenCostsV0; -use crate::data_contract::TokenContractPosition; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use derive_more::From; pub(crate) mod accessors; @@ -18,37 +17,37 @@ pub enum TokenCosts { /// Implementation of the `TokenCostGettersV0` trait for `TokenCosts` enum. impl TokenCostGettersV0 for TokenCosts { - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_creation_token_cost(&self) -> Option { match self { TokenCosts::V0(inner) => inner.document_creation_token_cost(), } } - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_replacement_token_cost(&self) -> Option { match self { TokenCosts::V0(inner) => inner.document_replacement_token_cost(), } } - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_deletion_token_cost(&self) -> Option { match self { TokenCosts::V0(inner) => inner.document_deletion_token_cost(), } } - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_transfer_token_cost(&self) -> Option { match self { TokenCosts::V0(inner) => inner.document_transfer_token_cost(), } } - fn document_price_update_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_price_update_token_cost(&self) -> Option { match self { TokenCosts::V0(inner) => inner.document_price_update_token_cost(), } } - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_purchase_token_cost(&self) -> Option { match self { TokenCosts::V0(inner) => inner.document_purchase_token_cost(), } @@ -56,55 +55,37 @@ impl TokenCostGettersV0 for TokenCosts { } impl TokenCostSettersV0 for TokenCosts { - fn set_document_creation_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_creation_token_cost(&mut self, cost: Option) { match self { TokenCosts::V0(inner) => inner.set_document_creation_token_cost(cost), } } - fn set_document_replacement_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_replacement_token_cost(&mut self, cost: Option) { match self { TokenCosts::V0(inner) => inner.set_document_replacement_token_cost(cost), } } - fn set_document_deletion_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_deletion_token_cost(&mut self, cost: Option) { match self { TokenCosts::V0(inner) => inner.set_document_deletion_token_cost(cost), } } - fn set_document_transfer_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_transfer_token_cost(&mut self, cost: Option) { match self { TokenCosts::V0(inner) => inner.set_document_transfer_token_cost(cost), } } - fn set_document_price_update_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_price_update_token_cost(&mut self, cost: Option) { match self { TokenCosts::V0(inner) => inner.set_document_price_update_token_cost(cost), } } - fn set_document_purchase_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_purchase_token_cost(&mut self, cost: Option) { match self { TokenCosts::V0(inner) => inner.set_document_purchase_token_cost(cost), } diff --git a/packages/rs-dpp/src/data_contract/document_type/token_costs/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/token_costs/v0/mod.rs index 661ed680872..345663540b3 100644 --- a/packages/rs-dpp/src/data_contract/document_type/token_costs/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/token_costs/v0/mod.rs @@ -1,99 +1,80 @@ -use crate::balances::credits::TokenAmount; use crate::data_contract::document_type::token_costs::accessors::{ TokenCostGettersV0, TokenCostSettersV0, }; -use crate::data_contract::TokenContractPosition; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; /// Token costs for various document operations. #[derive(Debug, PartialEq, Clone, Default)] pub struct TokenCostsV0 { /// Cost of creating a document. - pub create: Option<(TokenContractPosition, TokenAmount)>, + pub create: Option, /// Cost of replacing a document. - pub replace: Option<(TokenContractPosition, TokenAmount)>, + pub replace: Option, /// Cost of deleting a document. - pub delete: Option<(TokenContractPosition, TokenAmount)>, + pub delete: Option, /// Cost of transferring a document. - pub transfer: Option<(TokenContractPosition, TokenAmount)>, + pub transfer: Option, /// Cost of updating the price of a document. - pub update_price: Option<(TokenContractPosition, TokenAmount)>, + pub update_price: Option, /// Cost of purchasing a document. - pub purchase: Option<(TokenContractPosition, TokenAmount)>, + pub purchase: Option, } /// Implementation of the `TokenCostGettersV0` trait for `TokenCostsV0`. impl TokenCostGettersV0 for TokenCostsV0 { - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { - self.create.clone() + fn document_creation_token_cost(&self) -> Option { + self.create } - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { - self.replace.clone() + fn document_replacement_token_cost(&self) -> Option { + self.replace } - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { - self.delete.clone() + fn document_deletion_token_cost(&self) -> Option { + self.delete } - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { - self.transfer.clone() + fn document_transfer_token_cost(&self) -> Option { + self.transfer } - fn document_price_update_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { - self.update_price.clone() + fn document_price_update_token_cost(&self) -> Option { + self.update_price } - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { - self.purchase.clone() + fn document_purchase_token_cost(&self) -> Option { + self.purchase } } /// Implementation of the `TokenCostSettersV0` trait for `TokenCostsV0`. impl TokenCostSettersV0 for TokenCostsV0 { - fn set_document_creation_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_creation_token_cost(&mut self, cost: Option) { self.create = cost; } - fn set_document_replacement_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_replacement_token_cost(&mut self, cost: Option) { self.replace = cost; } - fn set_document_deletion_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_deletion_token_cost(&mut self, cost: Option) { self.delete = cost; } - fn set_document_transfer_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_transfer_token_cost(&mut self, cost: Option) { self.transfer = cost; } - fn set_document_price_update_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_price_update_token_cost(&mut self, cost: Option) { self.update_price = cost; } - fn set_document_purchase_token_cost( - &mut self, - cost: Option<(TokenContractPosition, TokenAmount)>, - ) { + fn set_document_purchase_token_cost(&mut self, cost: Option) { self.purchase = cost; } } diff --git a/packages/rs-dpp/src/data_contract/document_type/v0/accessors.rs b/packages/rs-dpp/src/data_contract/document_type/v0/accessors.rs index f04b9fa39fe..efc5da11ac8 100644 --- a/packages/rs-dpp/src/data_contract/document_type/v0/accessors.rs +++ b/packages/rs-dpp/src/data_contract/document_type/v0/accessors.rs @@ -1,5 +1,5 @@ use crate::data_contract::document_type::accessors::{ - DocumentTypeV0Getters, DocumentTypeV0Setters, + DocumentTypeV0Getters, DocumentTypeV0MutGetters, DocumentTypeV0Setters, }; use crate::data_contract::document_type::index::Index; use crate::data_contract::document_type::index_level::IndexLevel; @@ -18,6 +18,12 @@ use crate::nft::TradeMode; use indexmap::IndexMap; use std::collections::{BTreeMap, BTreeSet}; +impl DocumentTypeV0MutGetters for DocumentTypeV0 { + fn schema_mut(&mut self) -> &mut Value { + &mut self.schema + } +} + impl DocumentTypeV0Getters for DocumentTypeV0 { fn name(&self) -> &String { &self.name diff --git a/packages/rs-dpp/src/data_contract/document_type/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/v0/mod.rs index a2f2a28b991..69c62729fba 100644 --- a/packages/rs-dpp/src/data_contract/document_type/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/v0/mod.rs @@ -66,10 +66,3 @@ pub struct DocumentTypeV0 { impl DocumentTypeBasicMethods for DocumentTypeV0 {} impl DocumentTypeV0Methods for DocumentTypeV0 {} - -impl DocumentTypeV0 { - // Public method to set the data_contract_id - pub fn set_data_contract_id(&mut self, new_id: Identifier) { - self.data_contract_id = new_id; - } -} diff --git a/packages/rs-dpp/src/data_contract/document_type/v1/accessors.rs b/packages/rs-dpp/src/data_contract/document_type/v1/accessors.rs index 54caaa1fa8d..100224a3ebd 100644 --- a/packages/rs-dpp/src/data_contract/document_type/v1/accessors.rs +++ b/packages/rs-dpp/src/data_contract/document_type/v1/accessors.rs @@ -1,5 +1,5 @@ use crate::data_contract::document_type::accessors::{ - DocumentTypeV0Getters, DocumentTypeV0Setters, DocumentTypeV1Getters, + DocumentTypeV0Getters, DocumentTypeV0MutGetters, DocumentTypeV0Setters, DocumentTypeV1Getters, }; use crate::data_contract::document_type::index::Index; use crate::data_contract::document_type::index_level::IndexLevel; @@ -7,20 +7,25 @@ use crate::data_contract::document_type::property::DocumentProperty; use platform_value::{Identifier, Value}; -use crate::balances::credits::TokenAmount; use crate::data_contract::document_type::restricted_creation::CreationRestrictionMode; use crate::data_contract::document_type::token_costs::accessors::TokenCostGettersV0; use crate::data_contract::document_type::v1::DocumentTypeV1; #[cfg(feature = "validation")] use crate::data_contract::document_type::validator::StatelessJsonSchemaLazyValidator; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; -use crate::data_contract::TokenContractPosition; use crate::document::transfer::Transferable; use crate::identity::SecurityLevel; use crate::nft::TradeMode; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use indexmap::IndexMap; use std::collections::{BTreeMap, BTreeSet}; +impl DocumentTypeV0MutGetters for DocumentTypeV1 { + fn schema_mut(&mut self) -> &mut Value { + &mut self.schema + } +} + impl DocumentTypeV0Getters for DocumentTypeV1 { fn name(&self) -> &String { &self.name @@ -125,27 +130,27 @@ impl DocumentTypeV0Setters for DocumentTypeV1 { } impl DocumentTypeV1Getters for DocumentTypeV1 { - fn document_creation_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_creation_token_cost(&self) -> Option { self.token_costs.document_creation_token_cost() } - fn document_replacement_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_replacement_token_cost(&self) -> Option { self.token_costs.document_replacement_token_cost() } - fn document_deletion_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_deletion_token_cost(&self) -> Option { self.token_costs.document_deletion_token_cost() } - fn document_transfer_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_transfer_token_cost(&self) -> Option { self.token_costs.document_transfer_token_cost() } - fn document_update_price_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_update_price_token_cost(&self) -> Option { self.token_costs.document_price_update_token_cost() } - fn document_purchase_token_cost(&self) -> Option<(TokenContractPosition, TokenAmount)> { + fn document_purchase_token_cost(&self) -> Option { self.token_costs.document_purchase_token_cost() } } diff --git a/packages/rs-dpp/src/data_contract/document_type/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/v1/mod.rs index 1ca0be47843..ce7a0dd4f3f 100644 --- a/packages/rs-dpp/src/data_contract/document_type/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/v1/mod.rs @@ -6,19 +6,22 @@ use crate::data_contract::document_type::index_level::IndexLevel; use crate::data_contract::document_type::property::DocumentProperty; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; +use crate::data_contract::document_type::accessors::DocumentTypeV1Setters; use crate::data_contract::document_type::methods::{ DocumentTypeBasicMethods, DocumentTypeV0Methods, }; use crate::data_contract::document_type::restricted_creation::CreationRestrictionMode; +use crate::data_contract::document_type::token_costs::accessors::TokenCostSettersV0; use crate::data_contract::document_type::token_costs::TokenCosts; use crate::data_contract::document_type::v0::DocumentTypeV0; +#[cfg(feature = "validation")] +use crate::data_contract::document_type::validator::StatelessJsonSchemaLazyValidator; use crate::document::transfer::Transferable; use crate::identity::SecurityLevel; use crate::nft::TradeMode; +use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use platform_value::{Identifier, Value}; -#[cfg(feature = "validation")] -use crate::data_contract::document_type::validator::StatelessJsonSchemaLazyValidator; mod accessors; #[cfg(feature = "random-document-types")] pub mod random_document_type; @@ -71,10 +74,29 @@ impl DocumentTypeBasicMethods for DocumentTypeV1 {} impl DocumentTypeV0Methods for DocumentTypeV1 {} -impl DocumentTypeV1 { - // Public method to set the data_contract_id - pub fn set_data_contract_id(&mut self, new_id: Identifier) { - self.data_contract_id = new_id; +impl DocumentTypeV1Setters for DocumentTypeV1 { + fn set_document_creation_token_cost(&mut self, cost: Option) { + self.token_costs.set_document_creation_token_cost(cost) + } + + fn set_document_replacement_token_cost(&mut self, cost: Option) { + self.token_costs.set_document_replacement_token_cost(cost) + } + + fn set_document_deletion_token_cost(&mut self, cost: Option) { + self.token_costs.set_document_deletion_token_cost(cost) + } + + fn set_document_transfer_token_cost(&mut self, cost: Option) { + self.token_costs.set_document_transfer_token_cost(cost) + } + + fn set_document_price_update_token_cost(&mut self, cost: Option) { + self.token_costs.set_document_price_update_token_cost(cost) + } + + fn set_document_purchase_token_cost(&mut self, cost: Option) { + self.token_costs.set_document_purchase_token_cost(cost) } } diff --git a/packages/rs-dpp/src/document/document_factory/mod.rs b/packages/rs-dpp/src/document/document_factory/mod.rs index 158daf9488f..2d958c7eb8d 100644 --- a/packages/rs-dpp/src/document/document_factory/mod.rs +++ b/packages/rs-dpp/src/document/document_factory/mod.rs @@ -17,6 +17,7 @@ use crate::state_transition::batch_transition::{ batched_transition::document_transition_action_type::DocumentTransitionActionType, BatchTransition, }; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::util::entropy_generator::EntropyGenerator; pub use v0::DocumentFactoryV0; @@ -117,7 +118,12 @@ impl DocumentFactory { documents_iter: impl IntoIterator< Item = ( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef<'a>, Bytes32)>, + Vec<( + Document, + DocumentTypeRef<'a>, + Bytes32, + Option, + )>, ), >, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce diff --git a/packages/rs-dpp/src/document/document_factory/v0/mod.rs b/packages/rs-dpp/src/document/document_factory/v0/mod.rs index 5fa252dc973..d3ce7d6bbe9 100644 --- a/packages/rs-dpp/src/document/document_factory/v0/mod.rs +++ b/packages/rs-dpp/src/document/document_factory/v0/mod.rs @@ -34,6 +34,7 @@ use crate::state_transition::batch_transition::{ use itertools::Itertools; #[cfg(feature = "state-transitions")] use crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_transition::DocumentTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; const PROPERTY_FEATURE_VERSION: &str = "$version"; const PROPERTY_ENTROPY: &str = "$entropy"; @@ -208,7 +209,12 @@ impl DocumentFactoryV0 { documents_iter: impl IntoIterator< Item = ( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef<'a>, Bytes32)>, + Vec<( + Document, + DocumentTypeRef<'a>, + Bytes32, + Option, + )>, ), >, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce @@ -216,25 +222,25 @@ impl DocumentFactoryV0 { let platform_version = PlatformVersion::get(self.protocol_version)?; let documents: Vec<( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef, Bytes32)>, + Vec<(Document, DocumentTypeRef, Bytes32, Option)>, )> = documents_iter.into_iter().collect(); let mut flattened_documents_iter = documents.iter().flat_map(|(_, v)| v).peekable(); - let Some((first_document, _, _)) = flattened_documents_iter.peek() else { + let Some((first_document, _, _, _)) = flattened_documents_iter.peek() else { return Err(DocumentError::NoDocumentsSuppliedError.into()); }; let owner_id = first_document.owner_id(); let is_the_same_owner = - flattened_documents_iter.all(|(document, _, _)| document.owner_id() == owner_id); + flattened_documents_iter.all(|(document, _, _, _)| document.owner_id() == owner_id); if !is_the_same_owner { return Err(DocumentError::MismatchOwnerIdsError { documents: documents .into_iter() .flat_map(|(_, v)| { v.into_iter() - .map(|(document, _, _)| document) + .map(|(document, _, _, _)| document) .collect::>() }) .collect(), @@ -251,7 +257,9 @@ impl DocumentFactoryV0 { DocumentTransitionActionType::Delete => Self::document_delete_transitions( documents .into_iter() - .map(|(document, document_type, _)| (document, document_type)) + .map(|(document, document_type, _, token_payment_info)| { + (document, document_type, token_payment_info) + }) .collect(), nonce_counter, platform_version, @@ -259,7 +267,9 @@ impl DocumentFactoryV0 { DocumentTransitionActionType::Replace => Self::document_replace_transitions( documents .into_iter() - .map(|(document, document_type, _)| (document, document_type)) + .map(|(document, document_type, _, token_payment_info)| { + (document, document_type, token_payment_info) + }) .collect(), nonce_counter, platform_version, @@ -382,13 +392,13 @@ impl DocumentFactoryV0 { // #[cfg(feature = "state-transitions")] fn document_create_transitions( - documents: Vec<(Document, DocumentTypeRef, Bytes32)>, + documents: Vec<(Document, DocumentTypeRef, Bytes32, Option)>, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce platform_version: &PlatformVersion, ) -> Result, ProtocolError> { documents .into_iter() - .map(|(document, document_type, entropy)| { + .map(|(document, document_type, entropy, token_payment_info)| { if document_type.documents_mutable() { //we need to have revisions let Some(revision) = document.revision() else { @@ -412,6 +422,7 @@ impl DocumentFactoryV0 { document, document_type, entropy.to_buffer(), + token_payment_info, *nonce, platform_version, None, @@ -427,13 +438,13 @@ impl DocumentFactoryV0 { #[cfg(feature = "state-transitions")] fn document_replace_transitions( - documents: Vec<(Document, DocumentTypeRef)>, + documents: Vec<(Document, DocumentTypeRef, Option)>, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce platform_version: &PlatformVersion, ) -> Result, ProtocolError> { documents .into_iter() - .map(|(mut document, document_type)| { + .map(|(mut document, document_type, token_payment_info)| { if !document_type.documents_mutable() { return Err(DocumentError::TryingToReplaceImmutableDocument { document: Box::new(document), @@ -457,6 +468,7 @@ impl DocumentFactoryV0 { let transition = DocumentReplaceTransition::from_document( document, document_type, + token_payment_info, *nonce, platform_version, None, @@ -511,13 +523,13 @@ impl DocumentFactoryV0 { #[cfg(feature = "state-transitions")] fn document_delete_transitions( - documents: Vec<(Document, DocumentTypeRef)>, + documents: Vec<(Document, DocumentTypeRef, Option)>, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce platform_version: &PlatformVersion, ) -> Result, ProtocolError> { documents .into_iter() - .map(|(document, document_type)| { + .map(|(document, document_type, token_payment_info)| { if !document_type.documents_can_be_deleted() { return Err(DocumentError::TryingToDeleteIndelibleDocument { document: Box::new(document), @@ -537,6 +549,7 @@ impl DocumentFactoryV0 { let transition = DocumentDeleteTransition::from_document( document, document_type, + token_payment_info, *nonce, platform_version, None, @@ -604,7 +617,7 @@ mod test { let document = Document::V0(document_v0); // This will be passed to the factory - let documents = vec![(document, document_type_ref)]; + let documents = vec![(document, document_type_ref, None)]; let mut nonce_counter = BTreeMap::new(); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-dpp/src/document/specialized_document_factory/mod.rs b/packages/rs-dpp/src/document/specialized_document_factory/mod.rs index 0d7a25b3dcd..f006f3f2712 100644 --- a/packages/rs-dpp/src/document/specialized_document_factory/mod.rs +++ b/packages/rs-dpp/src/document/specialized_document_factory/mod.rs @@ -17,6 +17,7 @@ use crate::state_transition::batch_transition::{ batched_transition::document_transition_action_type::DocumentTransitionActionType, BatchTransition, }; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::util::entropy_generator::EntropyGenerator; pub use v0::SpecializedDocumentFactoryV0; @@ -120,7 +121,12 @@ impl SpecializedDocumentFactory { documents_iter: impl IntoIterator< Item = ( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef<'a>, Bytes32)>, + Vec<( + Document, + DocumentTypeRef<'a>, + Bytes32, + Option, + )>, ), >, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce diff --git a/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs b/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs index c89c7e34485..00faeba99a5 100644 --- a/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs +++ b/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs @@ -33,6 +33,7 @@ use crate::state_transition::batch_transition::{ use itertools::Itertools; #[cfg(feature = "state-transitions")] use crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_transition::DocumentTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; const PROPERTY_FEATURE_VERSION: &str = "$version"; const PROPERTY_ENTROPY: &str = "$entropy"; @@ -216,7 +217,12 @@ impl SpecializedDocumentFactoryV0 { documents_iter: impl IntoIterator< Item = ( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef<'a>, Bytes32)>, + Vec<( + Document, + DocumentTypeRef<'a>, + Bytes32, + Option, + )>, ), >, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce @@ -224,25 +230,25 @@ impl SpecializedDocumentFactoryV0 { let platform_version = PlatformVersion::get(self.protocol_version)?; let documents: Vec<( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef, Bytes32)>, + Vec<(Document, DocumentTypeRef, Bytes32, Option)>, )> = documents_iter.into_iter().collect(); let mut flattened_documents_iter = documents.iter().flat_map(|(_, v)| v).peekable(); - let Some((first_document, _, _)) = flattened_documents_iter.peek() else { + let Some((first_document, _, _, _)) = flattened_documents_iter.peek() else { return Err(DocumentError::NoDocumentsSuppliedError.into()); }; let owner_id = first_document.owner_id(); let is_the_same_owner = - flattened_documents_iter.all(|(document, _, _)| document.owner_id() == owner_id); + flattened_documents_iter.all(|(document, _, _, _)| document.owner_id() == owner_id); if !is_the_same_owner { return Err(DocumentError::MismatchOwnerIdsError { documents: documents .into_iter() .flat_map(|(_, v)| { v.into_iter() - .map(|(document, _, _)| document) + .map(|(document, _, _, _)| document) .collect::>() }) .collect(), @@ -259,7 +265,9 @@ impl SpecializedDocumentFactoryV0 { DocumentTransitionActionType::Delete => Self::document_delete_transitions( documents .into_iter() - .map(|(document, document_type, _)| (document, document_type)) + .map(|(document, document_type, _, token_payment_info)| { + (document, document_type, token_payment_info) + }) .collect(), nonce_counter, platform_version, @@ -267,7 +275,9 @@ impl SpecializedDocumentFactoryV0 { DocumentTransitionActionType::Replace => Self::document_replace_transitions( documents .into_iter() - .map(|(document, document_type, _)| (document, document_type)) + .map(|(document, document_type, _, token_payment_info)| { + (document, document_type, token_payment_info) + }) .collect(), nonce_counter, platform_version, @@ -391,13 +401,13 @@ impl SpecializedDocumentFactoryV0 { // #[cfg(feature = "state-transitions")] fn document_create_transitions( - documents: Vec<(Document, DocumentTypeRef, Bytes32)>, + documents: Vec<(Document, DocumentTypeRef, Bytes32, Option)>, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce platform_version: &PlatformVersion, ) -> Result, ProtocolError> { documents .into_iter() - .map(|(document, document_type, entropy)| { + .map(|(document, document_type, entropy, token_payment_info)| { if document_type.documents_mutable() { //we need to have revisions let Some(revision) = document.revision() else { @@ -421,6 +431,7 @@ impl SpecializedDocumentFactoryV0 { document, document_type, entropy.to_buffer(), + token_payment_info, *nonce, platform_version, None, @@ -436,13 +447,13 @@ impl SpecializedDocumentFactoryV0 { #[cfg(feature = "state-transitions")] fn document_replace_transitions( - documents: Vec<(Document, DocumentTypeRef)>, + documents: Vec<(Document, DocumentTypeRef, Option)>, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce platform_version: &PlatformVersion, ) -> Result, ProtocolError> { documents .into_iter() - .map(|(mut document, document_type)| { + .map(|(mut document, document_type, token_payment_info)| { if !document_type.documents_mutable() { return Err(DocumentError::TryingToReplaceImmutableDocument { document: Box::new(document), @@ -466,6 +477,7 @@ impl SpecializedDocumentFactoryV0 { let transition = DocumentReplaceTransition::from_document( document, document_type, + token_payment_info, *nonce, platform_version, None, @@ -520,13 +532,13 @@ impl SpecializedDocumentFactoryV0 { #[cfg(feature = "state-transitions")] fn document_delete_transitions( - documents: Vec<(Document, DocumentTypeRef)>, + documents: Vec<(Document, DocumentTypeRef, Option)>, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce platform_version: &PlatformVersion, ) -> Result, ProtocolError> { documents .into_iter() - .map(|(document, document_type)| { + .map(|(document, document_type, token_payment_info)| { if !document_type.documents_can_be_deleted() { return Err(DocumentError::TryingToDeleteIndelibleDocument { document: Box::new(document), @@ -545,6 +557,7 @@ impl SpecializedDocumentFactoryV0 { let transition = DocumentDeleteTransition::from_document( document, document_type, + token_payment_info, *nonce, platform_version, None, diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index 33eedfb1a47..187cf8f8e37 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -25,8 +25,8 @@ use crate::consensus::basic::data_contract::{ NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, SystemPropertyIndexAlreadyPresentError, UndefinedIndexPropertyError, UniqueIndicesLimitReachedError, UnknownDocumentCreationRestrictionModeError, - UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, - UnknownTransferableTypeError, + UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, + UnknownTradeModeError, UnknownTransferableTypeError, }; use crate::consensus::basic::decode::{ ProtocolVersionParsingError, SerializedObjectParsingError, VersionError, @@ -506,6 +506,9 @@ pub enum BasicError { #[error(transparent)] MissingDefaultLocalizationError(MissingDefaultLocalizationError), + + #[error(transparent)] + UnknownGasFeesPaidByError(UnknownGasFeesPaidByError), } impl From for ConsensusError { diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs index cf505b55967..ff5d8494284 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -38,6 +38,7 @@ mod system_property_index_already_present_error; mod undefined_index_property_error; mod unique_indices_limit_reached_error; mod unknown_document_creation_restriction_mode_error; +mod unknown_gas_fees_paid_by_error; mod unknown_security_level_error; mod unknown_storage_key_requirements_error; mod unknown_trade_mode_error; @@ -84,6 +85,7 @@ pub use invalid_token_distribution_function_invalid_parameter_tuple_error::*; pub use non_contiguous_contract_group_positions_error::*; pub use non_contiguous_contract_token_positions_error::*; pub use unknown_document_creation_restriction_mode_error::*; +pub use unknown_gas_fees_paid_by_error::*; pub use unknown_security_level_error::*; pub use unknown_storage_key_requirements_error::*; pub use unknown_trade_mode_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_gas_fees_paid_by_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_gas_fees_paid_by_error.rs new file mode 100644 index 00000000000..bd9dbbd4e4f --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_gas_fees_paid_by_error.rs @@ -0,0 +1,46 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error( + "Unrecognized gas fees paid by mode: allowed {:?}, got {}", + allowed_values, + received +)] +#[platform_serialize(unversioned)] +pub struct UnknownGasFeesPaidByError { + /* + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING A NEW VERSION + */ + allowed_values: Vec, + received: u64, +} + +impl UnknownGasFeesPaidByError { + pub fn new(allowed_values: Vec, received: u64) -> Self { + Self { + allowed_values, + received, + } + } + + pub fn allowed_values(&self) -> Vec { + self.allowed_values.clone() + } + + pub fn received(&self) -> u64 { + self.received + } +} + +impl From for ConsensusError { + fn from(err: UnknownGasFeesPaidByError) -> Self { + Self::BasicError(BasicError::UnknownGasFeesPaidByError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 5d25bef191a..5a0478ad24b 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -107,6 +107,7 @@ impl ErrorWithCode for BasicError { Self::InvalidTokenDistributionFunctionInvalidParameterTupleError(_) => 10256, Self::InvalidTokenDistributionFunctionIncoherenceError(_) => 10257, Self::MissingDefaultLocalizationError(_) => 10258, + Self::UnknownGasFeesPaidByError(_) => 10259, // Group Errors: 10350-10399 Self::GroupPositionDoesNotExistError(_) => 10350, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs index 88c136d585c..b6d464d1d91 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs @@ -2,7 +2,9 @@ use crate::data_contract::document_type::DocumentTypeRef; use crate::document::Document; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; +use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -10,6 +12,7 @@ impl DocumentBaseTransition { pub fn from_document( document: &Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, feature_version: Option, @@ -27,6 +30,13 @@ impl DocumentBaseTransition { identity_contract_nonce, ) .into()), + 1 => Ok(DocumentBaseTransitionV1::from_document( + document, + document_type, + token_payment_info, + identity_contract_nonce, + ) + .into()), version => Err(ProtocolError::UnknownVersionMismatch { method: "DocumentBaseTransition::from_document".to_string(), known_versions: vec![0], diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs index aeb16a1e0d4..9f1ed77111c 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/mod.rs @@ -14,6 +14,7 @@ use crate::data_contract::DataContract; use crate::state_transition::batch_transition::document_base_transition::v0::{ DocumentBaseTransitionV0, DocumentTransitionObjectLike, }; +use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; #[cfg(any( feature = "state-transition-value-conversion", feature = "state-transition-json-conversion" @@ -33,7 +34,6 @@ use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; #[cfg(feature = "state-transition-value-conversion")] use std::collections::BTreeMap; -use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; #[derive(Debug, Clone, Encode, Decode, PartialEq, Display, From)] #[cfg_attr( diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs index 6b4b5148815..919450b3e30 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v0/mod.rs @@ -68,12 +68,9 @@ impl DocumentBaseTransitionV0 { identity_contract_nonce: IdentityNonce, ) -> Result { Ok(DocumentBaseTransitionV0 { - id: Identifier::from( - map.remove_hash256_bytes(property_names::ID)?, - ), + id: Identifier::from(map.remove_hash256_bytes(property_names::ID)?), identity_contract_nonce, - document_type_name: map - .remove_string(property_names::DOCUMENT_TYPE)?, + document_type_name: map.remove_string(property_names::DOCUMENT_TYPE)?, data_contract_id: Identifier::new( map.remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID)? .unwrap_or(data_contract.id().to_buffer()), diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs index c457db10a44..69c4fd49bfb 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/from_document.rs @@ -3,11 +3,13 @@ use crate::data_contract::document_type::DocumentTypeRef; use crate::document::{Document, DocumentV0Getters}; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentBaseTransitionV1 { pub(in crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_base_transition) fn from_document( document: &Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, ) -> Self { DocumentBaseTransitionV1 { @@ -15,7 +17,7 @@ impl DocumentBaseTransitionV1 { identity_contract_nonce, document_type_name: document_type.name().to_string(), data_contract_id: document_type.data_contract_id(), - token_payment_info: None, + token_payment_info, } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs index 7edf1bc23b1..b4e9106422c 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/mod.rs @@ -7,24 +7,24 @@ use std::collections::BTreeMap; use bincode::{Decode, Encode}; use derive_more::Display; -#[cfg(feature = "state-transition-value-conversion")] -use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; -#[cfg(feature = "state-transition-value-conversion")] -use platform_value::Value; -#[cfg(feature = "state-transition-serde-conversion")] -use serde::{Deserialize, Serialize}; #[cfg(feature = "state-transition-value-conversion")] use crate::data_contract::accessors::v0::DataContractV0Getters; use crate::identifier::Identifier; use crate::prelude::IdentityNonce; #[cfg(feature = "state-transition-value-conversion")] use crate::state_transition::batch_transition::document_base_transition::property_names; +use crate::tokens::token_payment_info::TokenPaymentInfo; #[cfg(any( feature = "state-transition-json-conversion", feature = "state-transition-value-conversion" ))] use crate::{data_contract::DataContract, errors::ProtocolError}; -use crate::tokens::token_payment_info::TokenPaymentInfo; +#[cfg(feature = "state-transition-value-conversion")] +use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; +#[cfg(feature = "state-transition-value-conversion")] +use platform_value::Value; +#[cfg(feature = "state-transition-serde-conversion")] +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Encode, Decode, Default, PartialEq, Display)] #[cfg_attr( @@ -61,7 +61,7 @@ pub struct DocumentBaseTransitionV1 { feature = "state-transition-serde-conversion", serde(default, rename = "$tokenPaymentInfo") )] - pub token_payment_info: Option + pub token_payment_info: Option, } #[cfg(feature = "state-transition-value-conversion")] @@ -71,21 +71,23 @@ impl DocumentBaseTransitionV1 { data_contract: DataContract, identity_contract_nonce: IdentityNonce, ) -> Result { - let inner_token_payment_info_map: Option> = map.remove_optional_map_as_btree_map_keep_values_as_platform_value(property_names::TOKEN_PAYMENT_INFO).ok().flatten(); + let inner_token_payment_info_map: Option> = map + .remove_optional_map_as_btree_map_keep_values_as_platform_value( + property_names::TOKEN_PAYMENT_INFO, + ) + .ok() + .flatten(); Ok(DocumentBaseTransitionV1 { - id: Identifier::from( - map.remove_hash256_bytes(property_names::ID)?, - ), + id: Identifier::from(map.remove_hash256_bytes(property_names::ID)?), identity_contract_nonce, - document_type_name: map - .remove_string(property_names::DOCUMENT_TYPE)?, + document_type_name: map.remove_string(property_names::DOCUMENT_TYPE)?, data_contract_id: Identifier::new( map.remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID)? .unwrap_or(data_contract.id().to_buffer()), ), - token_payment_info: inner_token_payment_info_map.map(|map| { - map.try_into() - }).transpose()?, + token_payment_info: inner_token_payment_info_map + .map(|map| map.try_into()) + .transpose()?, }) } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs index 5c75fdfba33..1d185790619 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1/v1_methods.rs @@ -1,14 +1,14 @@ use crate::prelude::IdentityNonce; -use platform_value::Identifier; use crate::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; use crate::state_transition::batch_transition::document_base_transition::v1::DocumentBaseTransitionV1; use crate::tokens::token_payment_info::TokenPaymentInfo; +use platform_value::Identifier; /// A trait that contains getter and setter methods for `DocumentBaseTransitionV0` -pub trait DocumentBaseTransitionV1Methods : DocumentBaseTransitionV0Methods { +pub trait DocumentBaseTransitionV1Methods: DocumentBaseTransitionV0Methods { /// Returns the token payment info. fn token_payment_info(&self) -> Option; - + /// Returns the token payment info. fn token_payment_info_ref(&self) -> &Option; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs index 3b5edbc24b0..bc4538dccba 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/v1_methods.rs @@ -1,5 +1,5 @@ -use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use crate::state_transition::batch_transition::document_base_transition::v1::v1_methods::DocumentBaseTransitionV1Methods; +use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentBaseTransitionV1Methods for DocumentBaseTransition { @@ -19,15 +19,15 @@ impl DocumentBaseTransitionV1Methods for DocumentBaseTransition { fn set_token_payment_info(&mut self, token_payment_info: TokenPaymentInfo) { match self { - DocumentBaseTransition::V0(_) => { }, + DocumentBaseTransition::V0(_) => {} DocumentBaseTransition::V1(v1) => v1.set_token_payment_info(token_payment_info), } } fn clear_token_payment_info(&mut self) { match self { - DocumentBaseTransition::V0(_) => { }, + DocumentBaseTransition::V0(_) => {} DocumentBaseTransition::V1(v1) => v1.clear_token_payment_info(), } } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs index 800ab5d6c54..e3ca40a136b 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs @@ -30,17 +30,15 @@ use crate::state_transition::data_contract_update_transition::IDENTIFIER_FIELDS; feature = "state-transition-value-conversion" ))] use crate::ProtocolError; -#[cfg(any( - feature = "state-transition-json-conversion" -))] -use platform_value::btreemap_extensions::{ - BTreeValueMapHelper, BTreeValueMapReplacementPathHelper, -}; #[cfg(any( feature = "state-transition-json-conversion", feature = "state-transition-value-conversion" ))] use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; +#[cfg(any(feature = "state-transition-json-conversion"))] +use platform_value::btreemap_extensions::{ + BTreeValueMapHelper, BTreeValueMapReplacementPathHelper, +}; #[cfg(feature = "state-transition-json-conversion")] use platform_value::ReplacementType; #[cfg(any( diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs index 7ade005e6cf..dd05ddf03c6 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs @@ -3,6 +3,7 @@ use crate::document::Document; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::DocumentCreateTransition; use crate::state_transition::batch_transition::document_create_transition::DocumentCreateTransitionV0; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -11,6 +12,7 @@ impl DocumentCreateTransition { document: Document, document_type: DocumentTypeRef, entropy: [u8; 32], + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, feature_version: Option, @@ -28,6 +30,7 @@ impl DocumentCreateTransition { document, document_type, entropy, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/from_document.rs index 633c72ffccd..126062a1659 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/from_document.rs @@ -4,6 +4,7 @@ use crate::document::{Document, DocumentV0Getters}; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use crate::state_transition::batch_transition::document_create_transition::DocumentCreateTransitionV0; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -12,6 +13,7 @@ impl DocumentCreateTransitionV0 { document: Document, document_type: DocumentTypeRef, entropy: [u8; 32], + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, base_feature_version: Option, @@ -22,6 +24,7 @@ impl DocumentCreateTransitionV0 { base: DocumentBaseTransition::from_document( &document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs index 5d23d2f16c9..e9e2643caf4 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs @@ -197,87 +197,87 @@ impl DocumentFromCreateTransitionV0 for Document { { let DocumentCreateTransitionV0 { base, data, .. } = v0; - let requires_created_at = document_type - .required_fields() - .contains(document::property_names::CREATED_AT); - let requires_updated_at = document_type - .required_fields() - .contains(document::property_names::UPDATED_AT); - - let requires_created_at_block_height = document_type - .required_fields() - .contains(document::property_names::CREATED_AT_BLOCK_HEIGHT); - let requires_updated_at_block_height = document_type - .required_fields() - .contains(document::property_names::UPDATED_AT_BLOCK_HEIGHT); - - let requires_created_at_core_block_height = document_type - .required_fields() - .contains(document::property_names::CREATED_AT_CORE_BLOCK_HEIGHT); - let requires_updated_at_core_block_height = document_type - .required_fields() - .contains(document::property_names::UPDATED_AT_CORE_BLOCK_HEIGHT); - - let created_at = if requires_created_at { - Some(block_info.time_ms) - } else { - None - }; - let updated_at = if requires_updated_at { - Some(block_info.time_ms) - } else { - None - }; - - let created_at_block_height = if requires_created_at_block_height { - Some(block_info.height) - } else { - None - }; - let updated_at_block_height = if requires_updated_at_block_height { - Some(block_info.height) - } else { - None - }; - - let created_at_core_block_height = if requires_created_at_core_block_height { - Some(block_info.core_height) - } else { - None - }; - let updated_at_core_block_height = if requires_updated_at_core_block_height { - Some(block_info.core_height) - } else { - None - }; - - match platform_version - .dpp - .document_versions - .document_structure_version - { - 0 => Ok(DocumentV0 { - id: base.id(), - owner_id, - properties: data, - revision: document_type.initial_revision(), - created_at, - updated_at, - transferred_at: None, - created_at_block_height, - updated_at_block_height, - transferred_at_block_height: None, - created_at_core_block_height, - updated_at_core_block_height, - transferred_at_core_block_height: None, - } - .into()), - version => Err(ProtocolError::UnknownVersionMismatch { - method: "Document::try_from_create_transition_v0".to_string(), - known_versions: vec![0], - received: version, - }), - } + let requires_created_at = document_type + .required_fields() + .contains(document::property_names::CREATED_AT); + let requires_updated_at = document_type + .required_fields() + .contains(document::property_names::UPDATED_AT); + + let requires_created_at_block_height = document_type + .required_fields() + .contains(document::property_names::CREATED_AT_BLOCK_HEIGHT); + let requires_updated_at_block_height = document_type + .required_fields() + .contains(document::property_names::UPDATED_AT_BLOCK_HEIGHT); + + let requires_created_at_core_block_height = document_type + .required_fields() + .contains(document::property_names::CREATED_AT_CORE_BLOCK_HEIGHT); + let requires_updated_at_core_block_height = document_type + .required_fields() + .contains(document::property_names::UPDATED_AT_CORE_BLOCK_HEIGHT); + + let created_at = if requires_created_at { + Some(block_info.time_ms) + } else { + None + }; + let updated_at = if requires_updated_at { + Some(block_info.time_ms) + } else { + None + }; + + let created_at_block_height = if requires_created_at_block_height { + Some(block_info.height) + } else { + None + }; + let updated_at_block_height = if requires_updated_at_block_height { + Some(block_info.height) + } else { + None + }; + + let created_at_core_block_height = if requires_created_at_core_block_height { + Some(block_info.core_height) + } else { + None + }; + let updated_at_core_block_height = if requires_updated_at_core_block_height { + Some(block_info.core_height) + } else { + None + }; + + match platform_version + .dpp + .document_versions + .document_structure_version + { + 0 => Ok(DocumentV0 { + id: base.id(), + owner_id, + properties: data, + revision: document_type.initial_revision(), + created_at, + updated_at, + transferred_at: None, + created_at_block_height, + updated_at_block_height, + transferred_at_block_height: None, + created_at_core_block_height, + updated_at_core_block_height, + transferred_at_core_block_height: None, + } + .into()), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "Document::try_from_create_transition_v0".to_string(), + known_versions: vec![0], + received: version, + }), + } } fn try_from_create_transition_v0( @@ -292,87 +292,87 @@ impl DocumentFromCreateTransitionV0 for Document { { let DocumentCreateTransitionV0 { base, data, .. } = v0; - let requires_created_at = document_type - .required_fields() - .contains(document::property_names::CREATED_AT); - let requires_updated_at = document_type - .required_fields() - .contains(document::property_names::UPDATED_AT); - - let requires_created_at_block_height = document_type - .required_fields() - .contains(document::property_names::CREATED_AT_BLOCK_HEIGHT); - let requires_updated_at_block_height = document_type - .required_fields() - .contains(document::property_names::UPDATED_AT_BLOCK_HEIGHT); - - let requires_created_at_core_block_height = document_type - .required_fields() - .contains(document::property_names::CREATED_AT_CORE_BLOCK_HEIGHT); - let requires_updated_at_core_block_height = document_type - .required_fields() - .contains(document::property_names::UPDATED_AT_CORE_BLOCK_HEIGHT); - - let created_at = if requires_created_at { - Some(block_info.time_ms) - } else { - None - }; - let updated_at = if requires_updated_at { - Some(block_info.time_ms) - } else { - None - }; - - let created_at_block_height = if requires_created_at_block_height { - Some(block_info.height) - } else { - None - }; - let updated_at_block_height = if requires_updated_at_block_height { - Some(block_info.height) - } else { - None - }; - - let created_at_core_block_height = if requires_created_at_core_block_height { - Some(block_info.core_height) - } else { - None - }; - let updated_at_core_block_height = if requires_updated_at_core_block_height { - Some(block_info.core_height) - } else { - None - }; - - match platform_version - .dpp - .document_versions - .document_structure_version - { - 0 => Ok(DocumentV0 { - id: base.id(), - owner_id, - properties: data.clone(), - revision: document_type.initial_revision(), - created_at, - updated_at, - transferred_at: None, - created_at_block_height, - updated_at_block_height, - transferred_at_block_height: None, - created_at_core_block_height, - updated_at_core_block_height, - transferred_at_core_block_height: None, - } - .into()), - version => Err(ProtocolError::UnknownVersionMismatch { - method: "Document::try_from_owned_create_transition_v0".to_string(), - known_versions: vec![0], - received: version, - }), - } + let requires_created_at = document_type + .required_fields() + .contains(document::property_names::CREATED_AT); + let requires_updated_at = document_type + .required_fields() + .contains(document::property_names::UPDATED_AT); + + let requires_created_at_block_height = document_type + .required_fields() + .contains(document::property_names::CREATED_AT_BLOCK_HEIGHT); + let requires_updated_at_block_height = document_type + .required_fields() + .contains(document::property_names::UPDATED_AT_BLOCK_HEIGHT); + + let requires_created_at_core_block_height = document_type + .required_fields() + .contains(document::property_names::CREATED_AT_CORE_BLOCK_HEIGHT); + let requires_updated_at_core_block_height = document_type + .required_fields() + .contains(document::property_names::UPDATED_AT_CORE_BLOCK_HEIGHT); + + let created_at = if requires_created_at { + Some(block_info.time_ms) + } else { + None + }; + let updated_at = if requires_updated_at { + Some(block_info.time_ms) + } else { + None + }; + + let created_at_block_height = if requires_created_at_block_height { + Some(block_info.height) + } else { + None + }; + let updated_at_block_height = if requires_updated_at_block_height { + Some(block_info.height) + } else { + None + }; + + let created_at_core_block_height = if requires_created_at_core_block_height { + Some(block_info.core_height) + } else { + None + }; + let updated_at_core_block_height = if requires_updated_at_core_block_height { + Some(block_info.core_height) + } else { + None + }; + + match platform_version + .dpp + .document_versions + .document_structure_version + { + 0 => Ok(DocumentV0 { + id: base.id(), + owner_id, + properties: data.clone(), + revision: document_type.initial_revision(), + created_at, + updated_at, + transferred_at: None, + created_at_block_height, + updated_at_block_height, + transferred_at_block_height: None, + created_at_core_block_height, + updated_at_core_block_height, + transferred_at_core_block_height: None, + } + .into()), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "Document::try_from_owned_create_transition_v0".to_string(), + known_versions: vec![0], + received: version, + }), + } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs index a3eafe8c329..89ff4eafe77 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs @@ -6,11 +6,13 @@ use platform_version::version::{FeatureVersion, PlatformVersion}; use crate::state_transition::batch_transition::batched_transition::document_delete_transition::DocumentDeleteTransitionV0; use crate::state_transition::batch_transition::batched_transition::DocumentDeleteTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentDeleteTransition { pub fn from_document( document: Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, feature_version: Option, @@ -27,6 +29,7 @@ impl DocumentDeleteTransition { 0 => Ok(DocumentDeleteTransitionV0::from_document( document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/v0/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/v0/from_document.rs index 9a939350289..df7b4d2d77a 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/v0/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/v0/from_document.rs @@ -3,6 +3,7 @@ use crate::document::Document; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::document_delete_transition::DocumentDeleteTransitionV0; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -10,6 +11,7 @@ impl DocumentDeleteTransitionV0 { pub(crate) fn from_document( document: Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, base_feature_version: Option, @@ -18,6 +20,7 @@ impl DocumentDeleteTransitionV0 { base: DocumentBaseTransition::from_document( &document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs index b7f24dc3d1e..a559083cf35 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs @@ -7,12 +7,14 @@ use platform_version::version::{FeatureVersion, PlatformVersion}; use crate::state_transition::batch_transition::batched_transition::document_purchase_transition::DocumentPurchaseTransitionV0; use crate::state_transition::batch_transition::batched_transition::DocumentPurchaseTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentPurchaseTransition { pub fn from_document( document: Document, document_type: DocumentTypeRef, price: Credits, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, feature_version: Option, @@ -30,6 +32,7 @@ impl DocumentPurchaseTransition { document, document_type, price, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/v0/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/v0/from_document.rs index 9c2eb59f76e..d25745fa30b 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/v0/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/v0/from_document.rs @@ -5,6 +5,7 @@ use crate::fee::Credits; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::document_purchase_transition::DocumentPurchaseTransitionV0; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -13,6 +14,7 @@ impl DocumentPurchaseTransitionV0 { document: Document, document_type: DocumentTypeRef, price: Credits, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, base_feature_version: Option, @@ -29,6 +31,7 @@ impl DocumentPurchaseTransitionV0 { base: DocumentBaseTransition::from_document( &document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs index 1d2923a1f34..76adba03197 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs @@ -3,6 +3,7 @@ use crate::document::Document; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::document_replace_transition::DocumentReplaceTransitionV0; use crate::state_transition::batch_transition::batched_transition::DocumentReplaceTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -10,6 +11,7 @@ impl DocumentReplaceTransition { pub fn from_document( document: Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, feature_version: Option, @@ -26,6 +28,7 @@ impl DocumentReplaceTransition { 0 => Ok(DocumentReplaceTransitionV0::from_document( document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/v0/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/v0/from_document.rs index 4b5903c87ab..c51afdfceb4 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/v0/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/v0/from_document.rs @@ -4,6 +4,7 @@ use crate::document::{Document, DocumentV0Getters}; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::document_replace_transition::DocumentReplaceTransitionV0; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -11,6 +12,7 @@ impl DocumentReplaceTransitionV0 { pub(crate) fn from_document( document: Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, base_feature_version: Option, @@ -19,6 +21,7 @@ impl DocumentReplaceTransitionV0 { base: DocumentBaseTransition::from_document( &document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs index 17d0166f09f..b75d89d33f1 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs @@ -4,6 +4,7 @@ use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::document_transfer_transition::{ DocumentTransferTransition, DocumentTransferTransitionV0, }; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_value::Identifier; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -12,6 +13,7 @@ impl DocumentTransferTransition { pub fn from_document( document: Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, recipient_owner_id: Identifier, platform_version: &PlatformVersion, @@ -29,6 +31,7 @@ impl DocumentTransferTransition { 0 => Ok(DocumentTransferTransitionV0::from_document( document, document_type, + token_payment_info, identity_contract_nonce, recipient_owner_id, platform_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/v0/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/v0/from_document.rs index 7f182eb46a6..bed0d5dba00 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/v0/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/v0/from_document.rs @@ -4,6 +4,7 @@ use crate::document::{Document, DocumentV0Getters}; use crate::prelude::IdentityNonce; use crate::state_transition::batch_transition::batched_transition::document_transfer_transition::DocumentTransferTransitionV0; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_value::Identifier; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -12,6 +13,7 @@ impl DocumentTransferTransitionV0 { pub(crate) fn from_document( document: Document, document_type: DocumentTypeRef, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, recipient_owner_id: Identifier, platform_version: &PlatformVersion, @@ -21,6 +23,7 @@ impl DocumentTransferTransitionV0 { base: DocumentBaseTransition::from_document( &document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs index 39e2877d601..90a3216525d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs @@ -6,12 +6,14 @@ use crate::prelude::IdentityNonce; use crate::ProtocolError; use crate::state_transition::batch_transition::batched_transition::DocumentUpdatePriceTransition; use crate::state_transition::batch_transition::batched_transition::document_update_price_transition::DocumentUpdatePriceTransitionV0; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentUpdatePriceTransition { pub fn from_document( document: Document, document_type: DocumentTypeRef, price: Credits, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, feature_version: Option, @@ -29,6 +31,7 @@ impl DocumentUpdatePriceTransition { document, document_type, price, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/v0/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/v0/from_document.rs index 2a6c7785872..d190ca6ffdb 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/v0/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/v0/from_document.rs @@ -7,12 +7,14 @@ use crate::prelude::IdentityNonce; use crate::ProtocolError; use crate::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use crate::state_transition::batch_transition::batched_transition::document_update_price_transition::DocumentUpdatePriceTransitionV0; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentUpdatePriceTransitionV0 { pub(crate) fn from_document( document: Document, document_type: DocumentTypeRef, price: Credits, + token_payment_info: Option, identity_contract_nonce: IdentityNonce, platform_version: &PlatformVersion, base_feature_version: Option, @@ -21,6 +23,7 @@ impl DocumentUpdatePriceTransitionV0 { base: DocumentBaseTransition::from_document( &document, document_type, + token_payment_info, identity_contract_nonce, platform_version, base_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs index afe15fccbb4..00b8c30772d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs @@ -30,6 +30,7 @@ use crate::state_transition::batch_transition::{BatchTransitionV0, BatchTransiti use crate::state_transition::StateTransition; #[cfg(feature = "state-transition-signing")] use crate::tokens::emergency_action::TokenEmergencyAction; +use crate::tokens::token_payment_info::TokenPaymentInfo; #[cfg(feature = "state-transition-signing")] use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; use crate::ProtocolError; @@ -80,6 +81,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -101,6 +103,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -116,6 +119,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -138,6 +142,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -158,6 +163,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -172,6 +178,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -197,6 +204,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -218,6 +226,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -233,6 +242,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -257,6 +267,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -277,6 +288,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -291,6 +303,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -315,6 +328,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -336,6 +350,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -351,6 +366,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -377,6 +393,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -399,6 +416,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, @@ -415,6 +433,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransition { identity_public_key, identity_contract_nonce, user_fee_increase, + token_payment_info, signer, platform_version, batch_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs index eaadd2777a5..c6e80f4d208 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs @@ -22,6 +22,7 @@ use platform_version::version::{FeatureVersion, PlatformVersion}; use std::convert::TryFrom; use crate::state_transition::batch_transition::batched_transition::{BatchedTransition, BatchedTransitionRef}; use crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_transition::DocumentTransitionV0Methods; +use crate::tokens::token_payment_info::TokenPaymentInfo; pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 { #[cfg(feature = "state-transition-signing")] @@ -32,6 +33,7 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -46,6 +48,7 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -60,6 +63,7 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -75,6 +79,7 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -90,6 +95,7 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, @@ -106,6 +112,7 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, batch_feature_version: Option, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs index 17b7c8df12b..d3bc70fa3cf 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs @@ -39,6 +39,7 @@ use crate::state_transition::batch_transition::batched_transition::document_purc use crate::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; use crate::state_transition::batch_transition::resolvers::v0::BatchTransitionResolversV0; use crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_transition::DocumentTransitionV0Methods; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentsBatchTransitionAccessorsV0 for BatchTransitionV0 { type IterType<'a> @@ -85,6 +86,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -96,6 +98,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { document, document_type, entropy, + token_payment_info, identity_contract_nonce, platform_version, create_feature_version, @@ -125,6 +128,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -135,6 +139,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { let replace_transition = DocumentReplaceTransition::from_document( document, document_type, + token_payment_info, identity_contract_nonce, platform_version, replace_feature_version, @@ -165,6 +170,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -175,6 +181,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { let transfer_transition = DocumentTransferTransition::from_document( document, document_type, + token_payment_info, identity_contract_nonce, recipient_owner_id, platform_version, @@ -205,6 +212,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -215,6 +223,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { let delete_transition = DocumentDeleteTransition::from_document( document, document_type, + token_payment_info, identity_contract_nonce, platform_version, delete_feature_version, @@ -245,6 +254,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -256,6 +266,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { document, document_type, price, + token_payment_info, identity_contract_nonce, platform_version, update_price_feature_version, @@ -287,6 +298,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -297,6 +309,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV0 { document, document_type, price, + token_payment_info, identity_contract_nonce, platform_version, purchase_feature_version, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs index ee5a3f1919e..43aa411482e 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs @@ -85,6 +85,7 @@ use crate::state_transition::batch_transition::token_unfreeze_transition::TokenU use crate::tokens::emergency_action::TokenEmergencyAction; #[cfg(feature = "state-transition-signing")] use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentsBatchTransitionAccessorsV0 for BatchTransitionV1 { type IterType<'a> @@ -133,6 +134,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -144,6 +146,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { document, document_type, entropy, + token_payment_info, identity_contract_nonce, platform_version, create_feature_version, @@ -173,6 +176,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -183,6 +187,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { let replace_transition = DocumentReplaceTransition::from_document( document, document_type, + token_payment_info, identity_contract_nonce, platform_version, replace_feature_version, @@ -213,6 +218,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -223,6 +229,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { let transfer_transition = DocumentTransferTransition::from_document( document, document_type, + token_payment_info, identity_contract_nonce, recipient_owner_id, platform_version, @@ -253,6 +260,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -263,6 +271,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { let delete_transition = DocumentDeleteTransition::from_document( document, document_type, + token_payment_info, identity_contract_nonce, platform_version, delete_feature_version, @@ -293,6 +302,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -304,6 +314,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { document, document_type, price, + token_payment_info, identity_contract_nonce, platform_version, update_price_feature_version, @@ -335,6 +346,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, + token_payment_info: Option, signer: &S, platform_version: &PlatformVersion, _batch_feature_version: Option, @@ -345,6 +357,7 @@ impl DocumentsBatchTransitionMethodsV0 for BatchTransitionV1 { document, document_type, price, + token_payment_info, identity_contract_nonce, platform_version, purchase_feature_version, diff --git a/packages/rs-dpp/src/tests/fixtures/get_document_transitions_fixture.rs b/packages/rs-dpp/src/tests/fixtures/get_document_transitions_fixture.rs index d50516c4400..8942b86d7de 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_document_transitions_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_document_transitions_fixture.rs @@ -8,11 +8,18 @@ use crate::document::Document; use crate::state_transition::batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; use crate::state_transition::batch_transition::batched_transition::BatchedTransition; use crate::state_transition::batch_transition::batched_transition::document_transition_action_type::DocumentTransitionActionType; +use crate::tokens::token_payment_info::TokenPaymentInfo; + pub fn get_batched_transitions_fixture<'a>( documents: impl IntoIterator< Item = ( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef<'a>, Bytes32)>, + Vec<( + Document, + DocumentTypeRef<'a>, + Bytes32, + Option, + )>, ), >, nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce diff --git a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs index aa5c976f291..1f27b4cf02f 100644 --- a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs +++ b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs @@ -1,3 +1,7 @@ +use crate::consensus::basic::data_contract::UnknownGasFeesPaidByError; +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::ProtocolError; use bincode_derive::{Decode, Encode}; use derive_more::Display; use serde::{Deserialize, Serialize}; @@ -10,10 +14,55 @@ use serde::{Deserialize, Serialize}; pub enum GasFeesPaidBy { /// The user pays the gas fees #[default] - DocumentOwner, + DocumentOwner = 0, /// The contract owner pays the gas fees - ContractOwner, + ContractOwner = 1, /// The user is stating his willingness to pay the gas fee if the Contract owner's balance is /// insufficient. - PreferContractOwner, -} \ No newline at end of file + PreferContractOwner = 2, +} + +impl From for u8 { + fn from(value: GasFeesPaidBy) -> Self { + match value { + GasFeesPaidBy::DocumentOwner => 0, + GasFeesPaidBy::ContractOwner => 1, + GasFeesPaidBy::PreferContractOwner => 2, + } + } +} + +impl TryFrom for GasFeesPaidBy { + type Error = ProtocolError; + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(GasFeesPaidBy::DocumentOwner), + 1 => Ok(GasFeesPaidBy::ContractOwner), + 2 => Ok(GasFeesPaidBy::PreferContractOwner), + value => Err(ProtocolError::ConsensusError( + ConsensusError::BasicError(BasicError::UnknownGasFeesPaidByError( + UnknownGasFeesPaidByError::new(vec![0, 1], value as u64), + )) + .into(), + )), + } + } +} + +impl TryFrom for GasFeesPaidBy { + type Error = ProtocolError; + + fn try_from(value: u64) -> Result { + u8::try_from(value) + .map_err(|_| { + ProtocolError::ConsensusError( + ConsensusError::BasicError(BasicError::UnknownGasFeesPaidByError( + UnknownGasFeesPaidByError::new(vec![0, 1], value), + )) + .into(), + ) + })? + .try_into() + } +} diff --git a/packages/rs-dpp/src/tokens/mod.rs b/packages/rs-dpp/src/tokens/mod.rs index 71d9fda092f..c6da28ccd0b 100644 --- a/packages/rs-dpp/src/tokens/mod.rs +++ b/packages/rs-dpp/src/tokens/mod.rs @@ -7,11 +7,12 @@ use crate::util::hash::hash_double; pub mod allowed_currency; pub mod emergency_action; pub mod errors; +pub mod gas_fees_paid_by; pub mod info; pub mod status; +pub mod token_amount_on_contract_token; pub mod token_event; pub mod token_payment_info; -pub mod gas_fees_paid_by; pub const MAX_TOKEN_NOTE_LEN: usize = 2048; pub type SharedEncryptedNote = (SenderKeyIndex, RecipientKeyIndex, Vec); diff --git a/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs b/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs new file mode 100644 index 00000000000..2bb05571cb8 --- /dev/null +++ b/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs @@ -0,0 +1,16 @@ +use crate::balances::credits::TokenAmount; +use crate::data_contract::TokenContractPosition; +use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use platform_value::Identifier; + +#[derive(Debug, PartialEq, Clone, Copy, Default)] +pub struct DocumentActionTokenCost { + /// If this is not set, it means that we are using our own contract id + pub contract_id: Option, + /// Token contract position + pub token_contract_position: TokenContractPosition, + /// The amount + pub token_amount: TokenAmount, + /// Who is paying for gas fees for this action + pub gas_fees_paid_by: GasFeesPaidBy, +} diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs index 271e803671f..bcc1ae48e73 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -1,26 +1,26 @@ -use std::collections::BTreeMap; -use bincode_derive::{Decode, Encode}; -use derive_more::{Display, From}; -use serde::{Deserialize, Serialize}; -use platform_value::{Identifier, Value}; -use platform_value::btreemap_extensions::BTreeValueMapHelper; use crate::balances::credits::TokenAmount; use crate::data_contract::TokenContractPosition; -use crate::ProtocolError; use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; -use crate::tokens::token_payment_info::v0::TokenPaymentInfoV0; use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; +use crate::tokens::token_payment_info::v0::TokenPaymentInfoV0; +use crate::ProtocolError; +use bincode_derive::{Decode, Encode}; +use derive_more::{Display, From}; +use platform_value::btreemap_extensions::BTreeValueMapHelper; +use platform_value::{Identifier, Value}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; pub mod v0; #[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Display, From)] #[cfg_attr( feature = "state-transition-serde-conversion", - derive(Serialize, Deserialize), + derive(Serialize, Deserialize) )] pub enum TokenPaymentInfo { #[display("V0({})", "_0")] - V0(TokenPaymentInfoV0) + V0(TokenPaymentInfoV0), } impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfo { @@ -113,4 +113,4 @@ impl TryFrom> for TokenPaymentInfo { }), } } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs index 443add66591..dd8a93f13f1 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs @@ -1,16 +1,16 @@ pub mod v0_accessors; -use std::collections::BTreeMap; -use bincode_derive::{Decode, Encode}; -use derive_more::Display; -use serde::{Deserialize, Serialize}; -use platform_value::{Identifier, Value}; -use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; use crate::balances::credits::TokenAmount; use crate::data_contract::TokenContractPosition; -use crate::ProtocolError; use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; +use crate::ProtocolError; +use bincode_derive::{Decode, Encode}; +use derive_more::Display; +use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; +use platform_value::{Identifier, Value}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; #[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] #[cfg_attr( @@ -24,7 +24,7 @@ use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccesso token_contract_position, minimum_token_cost, maximum_token_cost, - gas_fees_paid_by, + gas_fees_paid_by )] pub struct TokenPaymentInfoV0 { /// By default, we use a token in the same contract, this field must be set if the document @@ -39,13 +39,13 @@ pub struct TokenPaymentInfoV0 { pub minimum_token_cost: Option, /// Maximum token cost, this most often should be set /// If: - /// - a client does not have this set + /// - a client does not have this set /// - and the data contract allows the price of NFTs to be changed by the data contract's owner or allowed party. /// Then: /// - The user could see the cost changed on them pub maximum_token_cost: Option, /// Who pays the gas fees, this needs to match what the contract allows - pub gas_fees_paid_by: GasFeesPaidBy + pub gas_fees_paid_by: GasFeesPaidBy, } impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfoV0 { @@ -122,4 +122,4 @@ impl TryFrom> for TokenPaymentInfoV0 { .unwrap_or_default(), }) } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs index 02324306df3..b2c03b84290 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/v0_accessors.rs @@ -1,7 +1,7 @@ -use platform_value::Identifier; use crate::balances::credits::TokenAmount; use crate::data_contract::TokenContractPosition; use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use platform_value::Identifier; /// Trait providing accessor and mutator methods for `TokenPaymentInfoV0`. pub trait TokenPaymentInfoAccessorsV0 { @@ -39,4 +39,4 @@ pub trait TokenPaymentInfoAccessorsV0 { /// Sets the `gas_fees_paid_by` strategy. fn set_gas_fees_paid_by(&mut self, payer: GasFeesPaidBy); -} \ No newline at end of file +} diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index 211e0ca86c3..966800cd816 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -2355,6 +2355,7 @@ mod tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2374,6 +2375,7 @@ mod tests { &key, 3, 0, + None, &signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs b/packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs index 2c0fe0a0275..13636d145f7 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs @@ -79,6 +79,7 @@ mod refund_tests { key, 2, 0, + None, signer, platform_version, None, @@ -186,6 +187,7 @@ mod refund_tests { key, 3, 0, + None, signer, platform_version, None, @@ -306,6 +308,7 @@ mod refund_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -405,6 +408,7 @@ mod refund_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -507,6 +511,7 @@ mod refund_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -605,6 +610,7 @@ mod refund_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -703,6 +709,7 @@ mod refund_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -802,6 +809,7 @@ mod refund_tests { &key, 4, 0, + None, &signer, &platform_version_with_higher_fees, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs index d3cdf285133..2ec96911633 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs @@ -154,7 +154,12 @@ mod test { let document_transitions = get_batched_transitions_fixture( [( DocumentTransitionActionType::Create, - vec![(contact_request_document, document_type, Bytes32::default())], + vec![( + contact_request_document, + document_type, + Bytes32::default(), + None, + )], )], &mut nonce_counter, ); @@ -257,7 +262,12 @@ mod test { let document_transitions = get_batched_transitions_fixture( [( DocumentTransitionActionType::Create, - vec![(contact_request_document, document_type, Bytes32::default())], + vec![( + contact_request_document, + document_type, + Bytes32::default(), + None, + )], )], &mut nonce_counter, ); @@ -385,7 +395,12 @@ mod test { let document_transitions = get_batched_transitions_fixture( [( DocumentTransitionActionType::Create, - vec![(contact_request_document, document_type, Bytes32::default())], + vec![( + contact_request_document, + document_type, + Bytes32::default(), + None, + )], )], &mut nonce_counter, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs index 55ffa746720..abbc3267b8f 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs @@ -425,7 +425,7 @@ mod test { let transitions = get_batched_transitions_fixture( [( DocumentTransitionActionType::Create, - vec![(document, document_type, Bytes32::default())], + vec![(document, document_type, Bytes32::default(), None)], )], &mut nonce_counter, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs index edc0ca1ddf8..f6e6e07bc1c 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/withdrawals/v0/mod.rs @@ -136,6 +136,7 @@ mod tests { use drive::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::v0::DocumentDeleteTransitionActionV0; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use dpp::tests::fixtures::{get_data_contract_fixture, get_withdrawal_document_fixture}; + use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; use dpp::version::PlatformVersion; use drive::util::object_size_info::DocumentInfo::DocumentRefInfo; use drive::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; @@ -169,6 +170,7 @@ mod tests { document_type_name: "".to_string(), data_contract: Arc::new(DataContractFetchInfo::dpns_contract_fixture(1)), token_cost: None, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, } .into(); @@ -312,6 +314,7 @@ mod tests { platform_version.protocol_version, )), token_cost: None, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, }), }), ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 1e4f8f30322..00eb850051d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -32,14 +32,20 @@ mod creation_tests { use dpp::consensus::state::state_error::StateError; use dpp::dashcore::Network; use dpp::dashcore::Network::Testnet; - use dpp::data_contract::DataContract; + use dpp::data_contract::{DataContract, TokenConfiguration}; use dpp::identity::SecurityLevel; use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use dpp::state_transition::batch_transition::document_create_transition::DocumentCreateTransitionV0; use dpp::state_transition::batch_transition::{DocumentCreateTransition, BatchTransitionV0}; use dpp::state_transition::StateTransition; use dpp::data_contract::accessors::v1::DataContractV1Getters; + use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; + use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; + use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; + use dpp::tokens::token_payment_info::TokenPaymentInfo; + use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; use crate::config::PlatformConfig; + use crate::execution::validation::state_transition::tests::{create_card_game_external_token_contract_with_owner_identity, create_token_contract_with_owner_identity}; #[test] fn test_document_creation() { @@ -87,6 +93,7 @@ mod creation_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -173,6 +180,7 @@ mod creation_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -235,6 +243,7 @@ mod creation_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -343,6 +352,7 @@ mod creation_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -523,6 +533,7 @@ mod creation_tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -544,6 +555,7 @@ mod creation_tests { &key_2, 2, 0, + None, &signer_2, platform_version, None, @@ -565,6 +577,7 @@ mod creation_tests { &key_1, 3, 0, + None, &signer_1, platform_version, None, @@ -585,6 +598,7 @@ mod creation_tests { &key_2, 3, 0, + None, &signer_2, platform_version, None, @@ -943,6 +957,7 @@ mod creation_tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -961,6 +976,7 @@ mod creation_tests { base: DocumentBaseTransition::from_document( &document_1, domain, + None, 3, platform_version, None, @@ -1215,6 +1231,7 @@ mod creation_tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -1233,6 +1250,7 @@ mod creation_tests { base: DocumentBaseTransition::from_document( &document_1, domain, + None, 3, platform_version, None, @@ -1561,6 +1579,7 @@ mod creation_tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -1582,6 +1601,7 @@ mod creation_tests { &key_2, 2, 0, + None, &signer_2, platform_version, None, @@ -1603,6 +1623,7 @@ mod creation_tests { &key_1, 3, 0, + None, &signer_1, platform_version, None, @@ -1624,6 +1645,7 @@ mod creation_tests { &key_1, 4, 0, + None, &signer_1, platform_version, None, @@ -1644,6 +1666,7 @@ mod creation_tests { &key_2, 3, 0, + None, &signer_2, platform_version, None, @@ -1664,6 +1687,7 @@ mod creation_tests { &key_1, 5, 0, + None, &signer_1, platform_version, None, @@ -2102,6 +2126,7 @@ mod creation_tests { &contender_1_key, 4, 0, + None, &contender_1_signer, platform_version, None, @@ -2333,6 +2358,7 @@ mod creation_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2395,6 +2421,7 @@ mod creation_tests { &another_identity_key, 2, 0, + None, &another_identity_signer, platform_version, None, @@ -2457,11 +2484,12 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); - let (contract, gold_token_id, _) = create_card_game_token_contract_with_owner_identity( - &mut platform, - contract_owner_id.id(), - platform_version, - ); + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity( + &mut platform, + contract_owner_id.id(), + platform_version, + ); let token_supply = platform .drive @@ -2509,6 +2537,7 @@ mod creation_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2578,11 +2607,12 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); - let (contract, gold_token_id, _) = create_card_game_token_contract_with_owner_identity( - &mut platform, - contract_owner_id.id(), - platform_version, - ); + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity( + &mut platform, + contract_owner_id.id(), + platform_version, + ); let token_supply = platform .drive @@ -2631,6 +2661,7 @@ mod creation_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2688,4 +2719,164 @@ mod creation_tests { // We should still have 8 assert_eq!(token_balance, Some(8)); } + + #[test] + fn test_document_creation_paid_with_an_external_token() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (document_contract_owner_id, _, _) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (token_contract_owner_id, _, _) = + setup_identity(&mut platform, 11, dash_to_credits!(0.1)); + + let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); + + let (token_contract, token_id) = create_token_contract_with_owner_identity( + &mut platform, + token_contract_owner_id.id(), + None::, + None, + None, + platform_version, + ); + + let document_contract = create_card_game_external_token_contract_with_owner_identity( + &mut platform, + token_contract.id(), + 0, + 5, + GasFeesPaidBy::DocumentOwner, + document_contract_owner_id.id(), + platform_version, + ); + + let token_supply = platform + .drive + .fetch_token_total_supply(token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(100000)); + + assert_eq!(token_contract.tokens().len(), 1); + + add_tokens_to_identity(&mut platform, token_id.into(), buyer.id(), 15); + + let token_supply = platform + .drive + .fetch_token_total_supply(token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(100015)); + + let card_document_type = document_contract + .document_type_for_name("card") + .expect("expected a profile document type"); + + assert_eq!( + card_document_type.document_creation_token_cost(), + Some(DocumentActionTokenCost { + contract_id: Some(token_contract.id()), + token_contract_position: 0, + token_amount: 5, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + }) + ); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = card_document_type + .random_document_with_identifier_and_entropy( + &mut rng, + buyer.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document.set("attack", 4.into()); + document.set("defense", 7.into()); + + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + card_document_type, + entropy.0, + &key, + 2, + 0, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: Some(token_contract.id()), + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(5), + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + assert_matches!( + documents_batch_create_transition, + StateTransition::Batch(BatchTransition::V1(_)) + ); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + token_id.to_buffer(), + buyer.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He had 15, but spent 5 + assert_eq!(token_balance, Some(10)); + } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs index 6a36155714f..f4930d1045f 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs @@ -2,7 +2,7 @@ use super::*; mod deletion_tests { use super::*; - use crate::execution::validation::state_transition::tests::create_card_game_token_contract_with_owner_identity; + use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity; #[test] fn test_document_delete_on_document_type_that_is_mutable_and_can_be_deleted() { @@ -58,6 +58,7 @@ mod deletion_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -101,6 +102,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -239,6 +241,7 @@ mod deletion_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -282,6 +285,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -403,6 +407,7 @@ mod deletion_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -446,6 +451,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -567,6 +573,7 @@ mod deletion_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -610,6 +617,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -702,6 +710,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -761,7 +770,7 @@ mod deletion_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity( &mut platform, contract_owner_id.id(), platform_version, @@ -800,6 +809,7 @@ mod deletion_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -859,6 +869,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -929,7 +940,7 @@ mod deletion_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity( &mut platform, contract_owner_id.id(), platform_version, @@ -967,6 +978,7 @@ mod deletion_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1026,6 +1038,7 @@ mod deletion_tests { &key, 3, 0, + None, &signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs index 284642a9c2b..2f8c396e11e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs @@ -214,6 +214,7 @@ mod dpns_tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -235,6 +236,7 @@ mod dpns_tests { &key_2, 2, 0, + None, &signer_2, platform_version, None, @@ -256,6 +258,7 @@ mod dpns_tests { &key_3, 2, 0, + None, &signer_3, platform_version, None, @@ -277,6 +280,7 @@ mod dpns_tests { &key_1, 3, 0, + None, &signer_1, platform_version, None, @@ -297,6 +301,7 @@ mod dpns_tests { &key_2, 3, 0, + None, &signer_2, platform_version, None, @@ -317,6 +322,7 @@ mod dpns_tests { &key_3, 3, 0, + None, &signer_3, platform_version, None, @@ -669,6 +675,7 @@ mod dpns_tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -690,6 +697,7 @@ mod dpns_tests { &key_2, 2, 0, + None, &signer_2, platform_version, None, @@ -711,6 +719,7 @@ mod dpns_tests { &key_3, 2, 0, + None, &signer_3, platform_version, None, @@ -732,6 +741,7 @@ mod dpns_tests { &key_1, 3, 0, + None, &signer_1, platform_version, None, @@ -752,6 +762,7 @@ mod dpns_tests { &key_2, 3, 0, + None, &signer_2, platform_version, None, @@ -772,6 +783,7 @@ mod dpns_tests { &key_3, 3, 0, + None, &signer_3, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs index c318efd8104..86270185659 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs @@ -7,4 +7,4 @@ mod transfer; use super::*; -use crate::execution::validation::state_transition::tests::create_card_game_token_contract_with_owner_identity; +use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs index 6ba047d4745..261bf06deb6 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs @@ -47,6 +47,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -117,6 +118,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -206,6 +208,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -299,6 +302,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -426,6 +430,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -545,6 +550,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -661,6 +667,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, @@ -821,6 +828,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -944,6 +952,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1039,6 +1048,7 @@ mod nft_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -1167,6 +1177,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, @@ -1326,6 +1337,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1449,6 +1461,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1567,6 +1580,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, @@ -1711,6 +1725,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1757,6 +1772,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1807,6 +1823,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, @@ -1903,6 +1920,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1949,6 +1967,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1999,6 +2018,7 @@ mod nft_tests { &key, 1, // 1 because he's never done anything 0, + None, &signer, platform_version, None, @@ -2100,6 +2120,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2146,6 +2167,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -2196,6 +2218,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, @@ -2307,6 +2330,7 @@ mod nft_tests { &key, 4, // 1 because he's never done anything 0, + None, &signer, platform_version, None, @@ -2402,6 +2426,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2495,6 +2520,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -2589,6 +2615,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, @@ -2681,6 +2708,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2729,6 +2757,7 @@ mod nft_tests { &other_identity_key, 1, 0, + None, &other_identity_signer, platform_version, None, @@ -2820,7 +2849,7 @@ mod nft_tests { setup_identity(&mut platform, 450, dash_to_credits!(1.0)); let (contract, gold_token_id, gas_token_id) = - create_card_game_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity( &mut platform, contract_owner_id.id(), platform_version, @@ -2874,6 +2903,7 @@ mod nft_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2970,6 +3000,7 @@ mod nft_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -3061,6 +3092,7 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, + None, &recipient_signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs index ec5a7071a5b..f2921d6ae74 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs @@ -61,6 +61,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -104,6 +105,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -213,6 +215,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -269,6 +272,7 @@ mod replacement_tests { &key, 3 + i as IdentityNonce, 0, + None, &signer, platform_version, None, @@ -559,6 +563,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -602,6 +607,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -689,6 +695,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -784,6 +791,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -891,6 +899,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -994,6 +1003,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1058,6 +1068,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1077,6 +1088,7 @@ mod replacement_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -1210,6 +1222,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1278,6 +1291,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1297,6 +1311,7 @@ mod replacement_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -1467,6 +1482,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1535,6 +1551,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1554,6 +1571,7 @@ mod replacement_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -1728,6 +1746,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1796,6 +1815,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -1815,6 +1835,7 @@ mod replacement_tests { &key, 4, 0, + None, &signer, platform_version, None, @@ -1946,7 +1967,7 @@ mod replacement_tests { let (creator, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity( &mut platform, contract_owner_id.id(), platform_version, @@ -1997,6 +2018,7 @@ mod replacement_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -2043,6 +2065,7 @@ mod replacement_tests { &key, 3, 0, + None, &signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs index 1c788428d1a..6040316f137 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs @@ -69,6 +69,7 @@ mod transfer_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -115,6 +116,7 @@ mod transfer_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -223,6 +225,7 @@ mod transfer_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -316,6 +319,7 @@ mod transfer_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -447,6 +451,7 @@ mod transfer_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -540,6 +545,7 @@ mod transfer_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -691,6 +697,7 @@ mod transfer_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -796,6 +803,7 @@ mod transfer_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -889,6 +897,7 @@ mod transfer_tests { &key, 3, 0, + None, &signer, platform_version, None, @@ -957,6 +966,7 @@ mod transfer_tests { &recipient_key, 2, 0, + None, &recipient_signer, platform_version, None, @@ -1035,7 +1045,7 @@ mod transfer_tests { let (receiver, _, _) = setup_identity(&mut platform, 450, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity( &mut platform, contract_owner_id.id(), platform_version, @@ -1088,6 +1098,7 @@ mod transfer_tests { &key, 2, 0, + None, &signer, platform_version, None, @@ -1181,6 +1192,7 @@ mod transfer_tests { &key, 3, 0, + None, &signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 1e867244856..a34392727b6 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -74,13 +74,14 @@ pub(in crate::execution) mod tests { use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::{get_contested_resource_vote_state_request_v0, GetContestedResourceVoteStateRequestV0}; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{get_contested_resource_vote_state_response_v0, GetContestedResourceVoteStateResponseV0}; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::get_contested_resource_vote_state_response_v0::FinishedVoteInfo; + use dpp::balances::credits::TokenAmount; use dpp::dash_to_credits; use dpp::dashcore::{ProTxHash, Txid}; use dpp::dashcore::hashes::Hash; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::accessors::v1::{DataContractV1Getters, DataContractV1Setters}; - use dpp::data_contract::{DataContract, GroupContractPosition}; - use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; + use dpp::data_contract::{DataContract, GroupContractPosition, TokenContractPosition}; + use dpp::data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV1Setters}; use dpp::data_contract::document_type::random_document::{CreateRandomDocument, DocumentFieldFillSize, DocumentFieldFillType}; use dpp::document::{Document, DocumentV0Getters, DocumentV0Setters}; use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; @@ -127,6 +128,9 @@ pub(in crate::execution) mod tests { use crate::execution::types::processed_block_fees_outcome::v0::ProcessedBlockFeesOutcome; use dpp::data_contract::associated_token::token_configuration::TokenConfiguration; use dpp::data_contract::group::Group; + use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; + use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; + use dpp::data_contract::document_type::accessors::DocumentTypeV0MutGetters; /// We add an identity, but we also add the same amount to system credits pub(in crate::execution) fn setup_identity_with_system_credits( @@ -1096,6 +1100,7 @@ pub(in crate::execution) mod tests { key_1, 2 + nonce_offset.unwrap_or_default(), 0, + None, signer_1, platform_version, None, @@ -1117,6 +1122,7 @@ pub(in crate::execution) mod tests { key_2, 2 + nonce_offset.unwrap_or_default(), 0, + None, signer_2, platform_version, None, @@ -1138,6 +1144,7 @@ pub(in crate::execution) mod tests { key_1, 3 + nonce_offset.unwrap_or_default(), 0, + None, signer_1, platform_version, None, @@ -1158,6 +1165,7 @@ pub(in crate::execution) mod tests { key_2, 3 + nonce_offset.unwrap_or_default(), 0, + None, signer_2, platform_version, None, @@ -1409,6 +1417,7 @@ pub(in crate::execution) mod tests { key_1, 2, 0, + None, signer_1, platform_version, None, @@ -1430,6 +1439,7 @@ pub(in crate::execution) mod tests { key_2, 2, 0, + None, signer_2, platform_version, None, @@ -1451,6 +1461,7 @@ pub(in crate::execution) mod tests { key_1, 3, 0, + None, signer_1, platform_version, None, @@ -1471,6 +1482,7 @@ pub(in crate::execution) mod tests { key_2, 3, 0, + None, signer_2, platform_version, None, @@ -1631,6 +1643,7 @@ pub(in crate::execution) mod tests { &key_1, 2, 0, + None, &signer_1, platform_version, None, @@ -1652,6 +1665,7 @@ pub(in crate::execution) mod tests { &key_1, 3, 0, + None, &signer_1, platform_version, None, @@ -2361,7 +2375,7 @@ pub(in crate::execution) mod tests { (basic_token_contract, token_id.into()) } - pub(in crate::execution) fn create_card_game_token_contract_with_owner_identity( + pub(in crate::execution) fn create_card_game_internal_token_contract_with_owner_identity( platform: &mut TempPlatform, identity_id: Identifier, platform_version: &PlatformVersion, @@ -2387,4 +2401,47 @@ pub(in crate::execution) mod tests { (basic_token_contract, token_id.into(), token_id_2.into()) } + + pub(in crate::execution) fn create_card_game_external_token_contract_with_owner_identity( + platform: &mut TempPlatform, + token_contract_id: Identifier, + token_contract_position: TokenContractPosition, + token_cost_amount: TokenAmount, + gas_fees_paid_by: GasFeesPaidBy, + identity_id: Identifier, + platform_version: &PlatformVersion, + ) -> DataContract { + let data_contract_id = DataContract::generate_data_contract_id_v0(identity_id, 1); + + let basic_token_contract = setup_contract( + &platform.drive, + "tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json", + Some(data_contract_id.to_buffer()), + Some(identity_id.to_buffer()), + Some(|data_contract: &mut DataContract| { + data_contract.set_created_at_epoch(Some(0)); + data_contract.set_created_at(Some(0)); + data_contract.set_created_at_block_height(Some(0)); + let document_type = data_contract.document_types_mut().get_mut("card").expect("expected a document type with name card"); + document_type.set_document_creation_token_cost(Some(DocumentActionTokenCost { + contract_id: Some(token_contract_id), + token_contract_position, + token_amount: token_cost_amount, + gas_fees_paid_by, + })); + let gas_fees_paid_by_int: u8 = gas_fees_paid_by.into(); + let schema = document_type.schema_mut(); + let token_cost = schema.get_mut("tokenCost").expect("expected to get token cost").expect("expected token cost to be set"); + let creation_token_cost = token_cost.get_mut("create").expect("expected to get creation token cost").expect("expected creation token cost to be set"); + creation_token_cost.set_value("contractId", token_contract_id.into()).expect("expected to set token contract id"); + creation_token_cost.set_value("tokenPosition", token_contract_position.into()).expect("expected to set token position"); + creation_token_cost.set_value("amount", token_cost_amount.into()).expect("expected to set token amount"); + creation_token_cost.set_value("gasFeesPaidBy", gas_fees_paid_by_int.into()).expect("expected to set token amount"); + }), + None, + Some(platform_version), + ); + + basic_token_contract + } } diff --git a/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json b/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json new file mode 100644 index 00000000000..4311665298e --- /dev/null +++ b/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json @@ -0,0 +1,137 @@ +{ + "$format_version": "1", + "id": "86LHvdC1Tqx5P97LQUSibGFqf2vnKFpB6VkqQ7oso86e", + "ownerId": "2QjL594djCH2NyDsn45vd6yQjEDHupMKo7CEGVTHtQxU", + "version": 1, + "documentSchemas": { + "card": { + "type": "object", + "documentsMutable": true, + "canBeDeleted": true, + "transferable": 1, + "tradeMode": 1, + "tokenCost": { + "create": { "contractId": "86LHvdC1Tqx5P97LQUSibGFqf2vnKFpB6VkqQ7oso86e", "tokenPosition": 0, "amount": 10, "gasFeesPaidBy": 1 } + }, + "properties": { + "name": { + "type": "string", + "description": "Name of the card", + "maxLength": 63, + "position": 0 + }, + "description": { + "type": "string", + "description": "Description of the card", + "maxLength": 256, + "position": 1 + }, + "imageUrl": { + "type": "string", + "description": "URL of the image associated with the card", + "maxLength": 2048, + "format": "uri", + "position": 2 + }, + "imageHash": { + "type": "array", + "description": "SHA256 hash of the bytes of the image specified by imageUrl", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 3 + }, + "imageFingerprint": { + "type": "array", + "description": "dHash of the image specified by imageUrl", + "byteArray": true, + "minItems": 8, + "maxItems": 8, + "position": 4 + }, + "attack": { + "type": "integer", + "description": "Attack power of the card", + "minimum": 0, + "position": 5 + }, + "defense": { + "type": "integer", + "description": "Defense level of the card", + "minimum": 0, + "position": 6 + } + }, + "indices": [ + { + "name": "owner", + "properties": [ + { + "$ownerId": "asc" + } + ] + }, + { + "name": "attack", + "properties": [ + { + "attack": "asc" + } + ] + }, + { + "name": "defense", + "properties": [ + { + "defense": "asc" + } + ] + }, + { + "name": "transferredAt", + "properties": [ + { + "$transferredAt": "asc" + } + ] + }, + { + "name": "ownerTransferredAt", + "properties": [ + { + "$ownerId": "asc" + }, + { + "$transferredAt": "asc" + } + ] + }, + { + "name": "transferredAtBlockHeight", + "properties": [ + { + "$transferredAtBlockHeight": "asc" + } + ] + }, + { + "name": "transferredAtCoreBlockHeight", + "properties": [ + { + "$transferredAtCoreBlockHeight": "asc" + } + ] + } + ], + "required": [ + "name", + "$transferredAt", + "$transferredAtBlockHeight", + "$transferredAtCoreBlockHeight", + "attack", + "defense" + ], + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs index 075693c6700..169a62ccf85 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs @@ -1,10 +1,9 @@ use dpp::platform_value::Identifier; use std::sync::Arc; -use dpp::balances::credits::TokenAmount; use dpp::data_contract::document_type::DocumentType; -use dpp::data_contract::TokenContractPosition; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use crate::drive::contract::DataContractFetchInfo; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionV0}; @@ -13,27 +12,31 @@ impl DocumentBaseTransitionAction { pub fn try_from_base_transition_with_contract_lookup( value: DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, + get_token_cost: impl Fn(&DocumentType) -> Option, ) -> Result { - Ok(DocumentBaseTransitionActionV0::try_from_base_transition_with_contract_lookup( - value, - get_data_contract, - get_token_cost, - )? - .into()) + Ok( + DocumentBaseTransitionActionV0::try_from_base_transition_with_contract_lookup( + value, + get_data_contract, + get_token_cost, + )? + .into(), + ) } /// from borrowed base transition with contract lookup pub fn try_from_borrowed_base_transition_with_contract_lookup( value: &DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, + get_token_cost: impl Fn(&DocumentType) -> Option, ) -> Result { - Ok(DocumentBaseTransitionActionV0::try_from_borrowed_base_transition_with_contract_lookup( - value, - get_data_contract, - get_token_cost, - )? - .into()) + Ok( + DocumentBaseTransitionActionV0::try_from_borrowed_base_transition_with_contract_lookup( + value, + get_data_contract, + get_token_cost, + )? + .into(), + ) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs index 7e252310a96..71a9e01f479 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs @@ -1,14 +1,14 @@ /// transformer pub mod transformer; +use crate::drive::contract::DataContractFetchInfo; use dpp::balances::credits::TokenAmount; use dpp::data_contract::document_type::DocumentTypeRef; use dpp::identifier::Identifier; use dpp::prelude::IdentityNonce; +use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; use dpp::ProtocolError; use std::sync::Arc; -use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; -use crate::drive::contract::DataContractFetchInfo; #[derive(Debug, Clone)] /// document base transition action v0 diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs index fb30f148711..6d2a54f1664 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs @@ -1,7 +1,5 @@ -use dpp::balances::credits::TokenAmount; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::DocumentType; -use dpp::data_contract::TokenContractPosition; use dpp::platform_value::Identifier; use std::sync::Arc; @@ -11,6 +9,7 @@ use dpp::state_transition::batch_transition::document_base_transition::v0::v0_me use dpp::state_transition::batch_transition::document_base_transition::v1::v1_methods::DocumentBaseTransitionV1Methods; use dpp::tokens::calculate_token_id; use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use dpp::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; use crate::drive::contract::DataContractFetchInfo; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionV0; @@ -20,21 +19,35 @@ impl DocumentBaseTransitionActionV0 { pub fn try_from_base_transition_with_contract_lookup( value: DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, + get_token_cost: impl Fn(&DocumentType) -> Option, ) -> Result { let data_contract_id = value.data_contract_id(); let data_contract = get_data_contract(data_contract_id)?; let document_type = data_contract .contract .document_type_borrowed_for_name(value.document_type_name().as_str())?; - let token_cost = - get_token_cost(document_type).map(|(token_contract_position, token_amount)| { + let token_cost = get_token_cost(document_type).map( + |DocumentActionTokenCost { + contract_id, + token_contract_position, + token_amount, + .. + }| { ( - calculate_token_id(data_contract_id.as_bytes(), token_contract_position).into(), + calculate_token_id( + contract_id.unwrap_or(data_contract_id).as_bytes(), + token_contract_position, + ) + .into(), token_amount, ) - }); - let gas_fees_paid_by = value.token_payment_info_ref().as_ref().map(|token_payment_info| token_payment_info.gas_fees_paid_by()).unwrap_or(GasFeesPaidBy::DocumentOwner); + }, + ); + let gas_fees_paid_by = value + .token_payment_info_ref() + .as_ref() + .map(|token_payment_info| token_payment_info.gas_fees_paid_by()) + .unwrap_or(GasFeesPaidBy::DocumentOwner); Ok(DocumentBaseTransitionActionV0 { id: value.id(), identity_contract_nonce: value.identity_contract_nonce(), @@ -49,21 +62,35 @@ impl DocumentBaseTransitionActionV0 { pub fn try_from_borrowed_base_transition_with_contract_lookup( value: &DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - get_token_cost: impl Fn(&DocumentType) -> Option<(TokenContractPosition, TokenAmount)>, + get_token_cost: impl Fn(&DocumentType) -> Option, ) -> Result { let data_contract_id = value.data_contract_id(); let data_contract = get_data_contract(data_contract_id)?; let document_type = data_contract .contract .document_type_borrowed_for_name(value.document_type_name().as_str())?; - let token_cost = - get_token_cost(document_type).map(|(token_contract_position, token_amount)| { + let token_cost = get_token_cost(document_type).map( + |DocumentActionTokenCost { + contract_id, + token_contract_position, + token_amount, + .. + }| { ( - calculate_token_id(data_contract_id.as_bytes(), token_contract_position).into(), + calculate_token_id( + contract_id.unwrap_or(data_contract_id).as_bytes(), + token_contract_position, + ) + .into(), token_amount, ) - }); - let gas_fees_paid_by = value.token_payment_info_ref().as_ref().map(|token_payment_info| token_payment_info.gas_fees_paid_by()).unwrap_or(GasFeesPaidBy::DocumentOwner); + }, + ); + let gas_fees_paid_by = value + .token_payment_info_ref() + .as_ref() + .map(|token_payment_info| token_payment_info.gas_fees_paid_by()) + .unwrap_or(GasFeesPaidBy::DocumentOwner); Ok(DocumentBaseTransitionActionV0 { id: value.id(), identity_contract_nonce: value.identity_contract_nonce(), diff --git a/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs b/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs index db6281a1ede..7e9b021b171 100644 --- a/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/system/bump_identity_data_contract_nonce_action/transformer.rs @@ -106,7 +106,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from borrowed base transition @@ -120,7 +120,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from base transition @@ -134,7 +134,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from borrowed base transition @@ -148,7 +148,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from base transition @@ -162,7 +162,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from borrowed base transition @@ -176,7 +176,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from base transition @@ -190,7 +190,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from borrowed base transition @@ -204,7 +204,7 @@ impl BumpIdentityDataContractNonceAction { identity_id, user_fee_increase, ) - .into() + .into() } /// from data contract update diff --git a/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs b/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs index 89389fa3cb3..d9a4b4acf95 100644 --- a/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs +++ b/packages/rs-platform-value/src/btreemap_extensions/btreemap_removal_extensions.rs @@ -60,7 +60,10 @@ pub trait BTreeValueRemoveFromMapHelper { K: TryFrom + Ord, V: TryFrom; - fn remove_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result, Error> + fn remove_map_as_btree_map_keep_values_as_platform_value( + &mut self, + key: &str, + ) -> Result, Error> where K: TryFrom + Ord; @@ -69,7 +72,7 @@ pub trait BTreeValueRemoveFromMapHelper { key: &str, ) -> Result>, Error> where - K: TryFrom + Ord; + K: TryFrom + Ord; } pub trait BTreeValueRemoveTupleFromMapHelper { @@ -353,17 +356,23 @@ impl BTreeValueRemoveFromMapHelper for BTreeMap { .transpose() } - fn remove_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result, Error> + fn remove_map_as_btree_map_keep_values_as_platform_value( + &mut self, + key: &str, + ) -> Result, Error> where - K: TryFrom + Ord + K: TryFrom + Ord, { self.remove_optional_map_as_btree_map_keep_values_as_platform_value(key)? .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}"))) } - fn remove_optional_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result>, Error> + fn remove_optional_map_as_btree_map_keep_values_as_platform_value( + &mut self, + key: &str, + ) -> Result>, Error> where - K: TryFrom + Ord + K: TryFrom + Ord, { self.remove(key) .and_then(|v| { @@ -372,9 +381,7 @@ impl BTreeValueRemoveFromMapHelper for BTreeMap { } else if let Value::Map(map) = v { Some( map.iter() - .map(|(key, value)| { - Ok((key.clone().try_into()?, value.clone())) - }) + .map(|(key, value)| Ok((key.clone().try_into()?, value.clone()))) .collect(), ) } else { @@ -664,7 +671,10 @@ impl BTreeValueRemoveFromMapHelper for BTreeMap { .transpose() } - fn remove_map_as_btree_map_keep_values_as_platform_value(&mut self, key: &str) -> Result, Error> + fn remove_map_as_btree_map_keep_values_as_platform_value( + &mut self, + key: &str, + ) -> Result, Error> where K: TryFrom + Ord, { diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v2.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v2.rs index 1df489c45e7..a6ad26bfa26 100644 --- a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v2.rs +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v2.rs @@ -58,7 +58,7 @@ pub const STATE_TRANSITION_SERIALIZATION_VERSIONS_V2: DPPStateTransitionSerializ document_base_state_transition: FeatureVersionBounds { min_version: 0, max_version: 0, - default_current_version: 0, + default_current_version: 1, }, document_create_state_transition: DocumentFeatureVersionBounds { bounds: FeatureVersionBounds { diff --git a/packages/rs-sdk/src/platform/transition/put_document.rs b/packages/rs-sdk/src/platform/transition/put_document.rs index a18b9143ea4..a61d978d2f6 100644 --- a/packages/rs-sdk/src/platform/transition/put_document.rs +++ b/packages/rs-sdk/src/platform/transition/put_document.rs @@ -67,6 +67,7 @@ impl PutDocument for Document { &identity_public_key, new_identity_contract_nonce, settings.user_fee_increase.unwrap_or_default(), + None, signer, sdk.version(), None, From 36d0454bc21b6fe87c7d6d0dd173df9658a3690a Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 27 Mar 2025 12:40:56 +0700 Subject: [PATCH 03/18] added extra tests --- .../src/errors/consensus/state/state_error.rs | 8 +- ...reed_to_pay_required_token_amount_error.rs | 81 +++ .../src/errors/consensus/state/token/mod.rs | 4 + ...quired_token_payment_info_not_set_error.rs | 55 ++ .../batch/tests/document/creation.rs | 534 +++++++++++++++++- 5 files changed, 680 insertions(+), 2 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs create mode 100644 packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index bdc0352eeab..7e8cc74793e 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -42,7 +42,7 @@ use crate::consensus::state::identity::missing_transfer_key_error::MissingTransf use crate::consensus::state::identity::no_transfer_key_for_core_withdrawal_available_error::NoTransferKeyForCoreWithdrawalAvailableError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; -use crate::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError, IdentityTokenAccountNotFrozenError, InvalidGroupPositionError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, NewTokensDestinationIdentityDoesNotExistError, TokenMintPastMaxSupplyError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, UnauthorizedTokenActionError, IdentityTokenAccountAlreadyFrozenError, TokenAlreadyPausedError, TokenIsPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, PreProgrammedDistributionTimestampInPastError, TokenTransferRecipientIdentityNotExistError}; +use crate::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError, IdentityTokenAccountNotFrozenError, InvalidGroupPositionError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, NewTokensDestinationIdentityDoesNotExistError, TokenMintPastMaxSupplyError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, UnauthorizedTokenActionError, IdentityTokenAccountAlreadyFrozenError, TokenAlreadyPausedError, TokenIsPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, PreProgrammedDistributionTimestampInPastError, TokenTransferRecipientIdentityNotExistError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError}; use crate::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; use crate::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use crate::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; @@ -282,6 +282,12 @@ pub enum StateError { #[error(transparent)] PreProgrammedDistributionTimestampInPastError(PreProgrammedDistributionTimestampInPastError), + + #[error(transparent)] + IdentityHasNotAgreedToPayRequiredTokenAmountError(IdentityHasNotAgreedToPayRequiredTokenAmountError), + + #[error(transparent)] + RequiredTokenPaymentInfoNotSetError(RequiredTokenPaymentInfoNotSetError), } impl From for ConsensusError { diff --git a/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs new file mode 100644 index 00000000000..c96784df1ce --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs @@ -0,0 +1,81 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::ProtocolError; +use crate::balances::credits::TokenAmount; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error( + "Identity {} has not agreed to pay the required token amount for token {}: required {}, min offer {:?}, max offer {:?}, action: {}", + identity_id, + token_id, + required_amount, + identity_min_offer, + identity_max_offer, + action +)] +#[platform_serialize(unversioned)] +pub struct IdentityHasNotAgreedToPayRequiredTokenAmountError { + token_id: Identifier, + identity_id: Identifier, + required_amount: u64, + identity_min_offer: Option, + identity_max_offer: Option, + action: String, +} + +impl IdentityHasNotAgreedToPayRequiredTokenAmountError { + #[allow(clippy::too_many_arguments)] + pub fn new( + token_id: Identifier, + identity_id: Identifier, + required_amount: u64, + identity_min_offer: Option, + identity_max_offer: Option, + action: String, + ) -> Self { + Self { + token_id, + identity_id, + required_amount, + identity_min_offer, + identity_max_offer, + action, + } + } + + pub fn token_id(&self) -> &Identifier { + &self.token_id + } + + pub fn identity_id(&self) -> &Identifier { + &self.identity_id + } + + pub fn required_amount(&self) -> u64 { + self.required_amount + } + + pub fn identity_min_offer(&self) -> Option { + self.identity_min_offer + } + + pub fn identity_max_offer(&self) -> Option { + self.identity_max_offer + } + + pub fn action(&self) -> &str { + &self.action + } +} + +impl From for ConsensusError { + fn from(err: IdentityHasNotAgreedToPayRequiredTokenAmountError) -> Self { + Self::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError(err)) + } +} \ No newline at end of file diff --git a/packages/rs-dpp/src/errors/consensus/state/token/mod.rs b/packages/rs-dpp/src/errors/consensus/state/token/mod.rs index f1f45d675a4..7a733641dc8 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/mod.rs @@ -18,6 +18,8 @@ mod token_not_paused_error; mod token_setting_max_supply_to_less_than_current_supply_error; mod token_transfer_recipient_identity_not_exist_error; mod unauthorized_token_action_error; +mod identity_has_not_agreed_to_pay_required_token_amount_error; +mod required_token_payment_info_not_set_error; pub use identity_does_not_have_enough_token_balance_error::*; pub use identity_token_account_already_frozen_error::*; @@ -39,3 +41,5 @@ pub use token_not_paused_error::*; pub use token_setting_max_supply_to_less_than_current_supply_error::*; pub use token_transfer_recipient_identity_not_exist_error::*; pub use unauthorized_token_action_error::*; +pub use identity_has_not_agreed_to_pay_required_token_amount_error::*; +pub use required_token_payment_info_not_set_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs new file mode 100644 index 00000000000..ada9b37eb51 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs @@ -0,0 +1,55 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error( + "Required token payment info not set for identity {} on token {} (action: {})", + identity_id, + token_id, + action +)] +#[platform_serialize(unversioned)] +pub struct RequiredTokenPaymentInfoNotSetError { + token_id: Identifier, + identity_id: Identifier, + action: String, +} + +impl RequiredTokenPaymentInfoNotSetError { + pub fn new( + token_id: Identifier, + identity_id: Identifier, + action: String, + ) -> Self { + Self { + token_id, + identity_id, + action, + } + } + + pub fn token_id(&self) -> &Identifier { + &self.token_id + } + + pub fn identity_id(&self) -> &Identifier { + &self.identity_id + } + + pub fn action(&self) -> &str { + &self.action + } +} + +impl From for ConsensusError { + fn from(err: RequiredTokenPaymentInfoNotSetError) -> Self { + Self::StateError(StateError::RequiredTokenPaymentInfoNotSetError(err)) + } +} \ No newline at end of file diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 00eb850051d..65eed6ff353 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -2537,7 +2537,13 @@ mod creation_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), &signer, platform_version, None, @@ -2590,6 +2596,532 @@ mod creation_tests { // He had 15, but spent 10 assert_eq!(token_balance, Some(5)); } + + #[test] + fn test_document_creation_paid_with_a_token_not_spending_enough() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (contract_owner_id, _, _) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); + + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity( + &mut platform, + contract_owner_id.id(), + platform_version, + ); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(0)); + + assert_eq!(contract.tokens().len(), 2); + + add_tokens_to_identity(&mut platform, gold_token_id.into(), buyer.id(), 15); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(15)); + + let card_document_type = contract + .document_type_for_name("card") + .expect("expected a profile document type"); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = card_document_type + .random_document_with_identifier_and_entropy( + &mut rng, + buyer.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document.set("attack", 4.into()); + document.set("defense", 7.into()); + + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + card_document_type, + entropy.0, + &key, + 2, + 0, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(9), + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [PaidConsensusError( + ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( + _ + )), + _ + )] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + buyer.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He should still have 15 + assert_eq!(token_balance, Some(15)); + } + + + #[test] + fn test_document_creation_paid_with_a_token_minimum_cost_set_rare_scenario() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (contract_owner_id, _, _) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); + + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity( + &mut platform, + contract_owner_id.id(), + platform_version, + ); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(0)); + + assert_eq!(contract.tokens().len(), 2); + + add_tokens_to_identity(&mut platform, gold_token_id.into(), buyer.id(), 15); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(15)); + + let card_document_type = contract + .document_type_for_name("card") + .expect("expected a profile document type"); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = card_document_type + .random_document_with_identifier_and_entropy( + &mut rng, + buyer.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document.set("attack", 4.into()); + document.set("defense", 7.into()); + + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + card_document_type, + entropy.0, + &key, + 2, + 0, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: Some(12), + maximum_token_cost: None, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [PaidConsensusError( + ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( + _ + )), + _ + )] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + buyer.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He should still have 15 + assert_eq!(token_balance, Some(15)); + } + + #[test] + fn test_document_creation_paid_with_a_token_agreeing_to_too_much() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (contract_owner_id, _, _) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); + + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity( + &mut platform, + contract_owner_id.id(), + platform_version, + ); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(0)); + + assert_eq!(contract.tokens().len(), 2); + + add_tokens_to_identity(&mut platform, gold_token_id.into(), buyer.id(), 15); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(15)); + + let card_document_type = contract + .document_type_for_name("card") + .expect("expected a profile document type"); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = card_document_type + .random_document_with_identifier_and_entropy( + &mut rng, + buyer.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document.set("attack", 4.into()); + document.set("defense", 7.into()); + + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + card_document_type, + entropy.0, + &key, + 2, + 0, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(12), + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + buyer.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He had 15, but only spent 10 + assert_eq!(token_balance, Some(5)); + } + + #[test] + fn test_document_creation_paid_with_a_token_token_info_not_set() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (contract_owner_id, _, _) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); + + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity( + &mut platform, + contract_owner_id.id(), + platform_version, + ); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(0)); + + assert_eq!(contract.tokens().len(), 2); + + add_tokens_to_identity(&mut platform, gold_token_id.into(), buyer.id(), 15); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(15)); + + let card_document_type = contract + .document_type_for_name("card") + .expect("expected a profile document type"); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = card_document_type + .random_document_with_identifier_and_entropy( + &mut rng, + buyer.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document.set("attack", 4.into()); + document.set("defense", 7.into()); + + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + card_document_type, + entropy.0, + &key, + 2, + 0, + None, + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [PaidConsensusError( + ConsensusError::StateError(StateError::RequiredTokenPaymentInfoNotSetError( + _ + )), + _ + )] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + buyer.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // Nothing should have happened + assert_eq!(token_balance, Some(15)); + } #[test] fn test_document_creation_not_enough_token_balance_to_create_document() { From 19e2b98cd37d4cfadce31ca42ccaa5ff8b1d34ee Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 28 Mar 2025 10:08:15 +0700 Subject: [PATCH 04/18] temp --- .../document/extended_document/accessors.rs | 8 + .../src/document/extended_document/fields.rs | 1 + .../src/document/extended_document/mod.rs | 5 +- .../src/document/extended_document/v0/mod.rs | 8 +- .../extended_document/v1/json_conversion.rs | 54 ++ .../src/document/extended_document/v1/mod.rs | 560 ++++++++++++++++++ .../v1/platform_value_conversion.rs | 77 +++ .../extended_document/v1/serialize.rs | 213 +++++++ packages/rs-dpp/src/errors/consensus/codes.rs | 2 + packages/rs-dpp/src/errors/protocol_error.rs | 3 + .../src/state_transition/serialization.rs | 1 + .../data_triggers/triggers/dashpay/v0/mod.rs | 6 +- .../data_triggers/triggers/dpns/v0/mod.rs | 2 +- .../batch/transformer/v0/mod.rs | 57 +- .../transformer.rs | 25 +- .../v0/transformer.rs | 60 +- .../transformer.rs | 25 +- .../v0/transformer.rs | 66 ++- .../transformer.rs | 19 +- .../v0/transformer.rs | 32 +- .../transformer.rs | 20 +- .../v0/transformer.rs | 49 +- .../transformer.rs | 20 +- .../v0/transformer.rs | 28 +- .../transformer.rs | 20 +- .../v0/transformer.rs | 28 +- .../batch/batched_transition/mod.rs | 43 ++ .../platform/transition/purchase_document.rs | 7 + .../platform/transition/transfer_document.rs | 7 + .../transition/update_price_of_document.rs | 8 +- packages/wasm-dpp/src/document/factory.rs | 6 +- .../document_transition/mod.rs | 5 +- .../src/errors/consensus/consensus_error.rs | 13 +- 33 files changed, 1320 insertions(+), 158 deletions(-) create mode 100644 packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs create mode 100644 packages/rs-dpp/src/document/extended_document/v1/mod.rs create mode 100644 packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs create mode 100644 packages/rs-dpp/src/document/extended_document/v1/serialize.rs diff --git a/packages/rs-dpp/src/document/extended_document/accessors.rs b/packages/rs-dpp/src/document/extended_document/accessors.rs index a471124d21f..c88e4ceab91 100644 --- a/packages/rs-dpp/src/document/extended_document/accessors.rs +++ b/packages/rs-dpp/src/document/extended_document/accessors.rs @@ -7,6 +7,7 @@ use crate::prelude::{BlockHeight, CoreBlockHeight, Revision}; use crate::ProtocolError; use platform_value::{Bytes32, Identifier, Value}; use std::collections::BTreeMap; +use crate::tokens::token_payment_info::TokenPaymentInfo; impl ExtendedDocument { /// Returns an immutable reference to the properties of the document. @@ -152,6 +153,13 @@ impl ExtendedDocument { } } + /// Returns a reference to the actual document object containing the data. + pub fn token_payment_info(&self) -> Option { + match self { + ExtendedDocument::V0(v0) => v0.token_payment_info, + } + } + /// Returns a reference to the data contract associated with the document. pub fn data_contract(&self) -> &DataContract { match self { diff --git a/packages/rs-dpp/src/document/extended_document/fields.rs b/packages/rs-dpp/src/document/extended_document/fields.rs index 09400b60edd..4f1351c4045 100644 --- a/packages/rs-dpp/src/document/extended_document/fields.rs +++ b/packages/rs-dpp/src/document/extended_document/fields.rs @@ -2,6 +2,7 @@ pub mod property_names { pub const FEATURE_VERSION: &str = "$version"; pub const ID: &str = "$id"; pub const DOCUMENT_TYPE_NAME: &str = "$type"; + pub const TOKEN_PAYMENT_INFO: &str = "$tokenPaymentInfo"; pub const REVISION: &str = "$revision"; pub const DATA_CONTRACT: &str = "$dataContract"; pub const DATA_CONTRACT_ID: &str = "$dataContractId"; diff --git a/packages/rs-dpp/src/document/extended_document/mod.rs b/packages/rs-dpp/src/document/extended_document/mod.rs index 2901850d30b..c48d2e07659 100644 --- a/packages/rs-dpp/src/document/extended_document/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/mod.rs @@ -4,6 +4,7 @@ mod fields; mod serde_serialize; mod serialize; pub(crate) mod v0; +pub(crate) mod v1; pub use fields::{property_names, IDENTIFIER_FIELDS}; @@ -27,10 +28,12 @@ use platform_versioning::PlatformVersioned; use serde_json::Value as JsonValue; #[cfg(feature = "document-value-conversion")] use std::collections::BTreeMap; +use derive_more::From; -#[derive(Debug, Clone, PlatformVersioned)] +#[derive(Debug, Clone, PlatformVersioned, From)] pub enum ExtendedDocument { V0(ExtendedDocumentV0), + V1(ExtendedDocumentV1), } impl ExtendedDocument { diff --git a/packages/rs-dpp/src/document/extended_document/v0/mod.rs b/packages/rs-dpp/src/document/extended_document/v0/mod.rs index d048b97a3ac..226502b2172 100644 --- a/packages/rs-dpp/src/document/extended_document/v0/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/v0/mod.rs @@ -509,10 +509,4 @@ impl ExtendedDocumentV0 { platform_version, ) } -} - -impl From for ExtendedDocument { - fn from(value: ExtendedDocumentV0) -> Self { - ExtendedDocument::V0(value) - } -} +} \ No newline at end of file diff --git a/packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs b/packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs new file mode 100644 index 00000000000..cbc8cb4a266 --- /dev/null +++ b/packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs @@ -0,0 +1,54 @@ +use crate::data_contract::conversion::json::DataContractJsonConversionMethodsV0; +use crate::document::extended_document::fields::property_names; +use crate::document::extended_document::v0::ExtendedDocumentV0; +use crate::document::serialization_traits::{ + DocumentJsonMethodsV0, DocumentPlatformValueMethodsV0, +}; + +use crate::ProtocolError; +use platform_value::Identifier; +use platform_version::version::PlatformVersion; +use serde::Deserialize; +use serde_json::Value as JsonValue; +use std::convert::TryInto; + +impl DocumentJsonMethodsV0<'_> for ExtendedDocumentV0 { + fn to_json_with_identifiers_using_bytes( + &self, + platform_version: &PlatformVersion, + ) -> Result { + let mut json = self + .document + .to_json_with_identifiers_using_bytes(platform_version)?; + let value_mut = json.as_object_mut().unwrap(); + let contract = self.data_contract.to_validating_json(platform_version)?; + value_mut.insert(property_names::DATA_CONTRACT.to_owned(), contract); + value_mut.insert( + property_names::DOCUMENT_TYPE_NAME.to_owned(), + self.document_type_name.clone().into(), + ); + Ok(json) + } + + fn to_json(&self, platform_version: &PlatformVersion) -> Result { + let mut json = self.document.to_json(platform_version)?; + let value_mut = json.as_object_mut().unwrap(); + let contract = self.data_contract.to_json(platform_version)?; + value_mut.insert(property_names::DATA_CONTRACT.to_owned(), contract); + value_mut.insert( + property_names::DOCUMENT_TYPE_NAME.to_owned(), + self.document_type_name.clone().into(), + ); + Ok(json) + } + + fn from_json_value( + document_value: JsonValue, + platform_version: &PlatformVersion, + ) -> Result + where + for<'de> S: Deserialize<'de> + TryInto, + { + Self::from_platform_value(document_value.into(), platform_version) + } +} diff --git a/packages/rs-dpp/src/document/extended_document/v1/mod.rs b/packages/rs-dpp/src/document/extended_document/v1/mod.rs new file mode 100644 index 00000000000..65b269897b8 --- /dev/null +++ b/packages/rs-dpp/src/document/extended_document/v1/mod.rs @@ -0,0 +1,560 @@ +#[cfg(feature = "document-json-conversion")] +mod json_conversion; +#[cfg(feature = "document-value-conversion")] +mod platform_value_conversion; +mod serialize; + +use crate::data_contract::document_type::DocumentTypeRef; +use crate::data_contract::DataContract; +#[cfg(any( + feature = "document-value-conversion", + feature = "document-json-conversion" +))] +use crate::document::extended_document::fields::property_names; +use crate::document::{Document, DocumentV0Getters, ExtendedDocument}; +use crate::identity::TimestampMillis; +use crate::metadata::Metadata; +use crate::prelude::{BlockHeight, CoreBlockHeight, Revision}; + +use crate::util::hash::hash_double_to_vec; +use crate::ProtocolError; + +use platform_value::btreemap_extensions::{ + BTreeValueMapInsertionPathHelper, BTreeValueMapPathHelper, +}; +#[cfg(feature = "document-value-conversion")] +use platform_value::btreemap_extensions::{ + BTreeValueMapReplacementPathHelper, BTreeValueRemoveFromMapHelper, +}; +use platform_value::{Bytes32, Identifier, ReplacementType, Value}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +use crate::data_contract::accessors::v0::DataContractV0Getters; +use crate::data_contract::document_type::accessors::DocumentTypeV0Getters; +use crate::data_contract::document_type::methods::DocumentTypeBasicMethods; +#[cfg(feature = "validation")] +use crate::data_contract::validate_document::DataContractDocumentValidationMethodsV0; +#[cfg(feature = "document-json-conversion")] +use crate::document::serialization_traits::DocumentJsonMethodsV0; +#[cfg(feature = "document-value-conversion")] +use crate::document::serialization_traits::DocumentPlatformValueMethodsV0; +use crate::document::serialization_traits::ExtendedDocumentPlatformConversionMethodsV0; +#[cfg(feature = "validation")] +use crate::validation::SimpleConsensusValidationResult; +#[cfg(feature = "document-json-conversion")] +use platform_value::converter::serde_json::BTreeValueJsonConverter; +use platform_version::version::PlatformVersion; +#[cfg(feature = "document-json-conversion")] +use serde_json::Value as JsonValue; +use crate::tokens::token_payment_info::TokenPaymentInfo; + +/// The `ExtendedDocumentV0` struct represents the data provided by the platform in response to a query. +#[derive(Debug, Clone)] +#[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + derive(Serialize, Deserialize) +)] +pub struct ExtendedDocumentV1 { + /// The document type name, stored as a string. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$type") + )] + pub document_type_name: String, + + /// The identifier of the associated data contract. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$dataContractId") + )] + pub data_contract_id: Identifier, + + /// The actual document object containing the data. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(flatten) + )] + pub document: Document, + + // TODO: We should remove it from here, or at least keep a ref + // also there is no point to keep both contract and its ID + /// The data contract associated with the document. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$dataContract") + )] + pub data_contract: DataContract, + + /// An optional field for metadata associated with the document. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$metadata", default) + )] + pub metadata: Option, + + /// A field representing the entropy, stored as `Bytes32`. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$entropy") + )] + pub entropy: Bytes32, + /// A field representing the token payment info. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$tokenPaymentInfo") + )] + pub token_payment_info: Option, +} + +impl ExtendedDocumentV1 { + #[cfg(feature = "document-json-conversion")] + pub(super) fn properties_as_json_data(&self) -> Result { + self.document + .properties() + .to_json_value() + .map_err(ProtocolError::ValueError) + } + + pub fn get_optional_value(&self, key: &str) -> Option<&Value> { + self.document.properties().get(key) + } + + pub fn properties(&self) -> &BTreeMap { + self.document.properties() + } + + pub fn properties_as_mut(&mut self) -> &mut BTreeMap { + self.document.properties_mut() + } + + pub fn id(&self) -> Identifier { + self.document.id() + } + + pub fn owner_id(&self) -> Identifier { + self.document.owner_id() + } + + pub fn document_type(&self) -> Result { + // We can unwrap because the Document can not be created without a valid Document Type + self.data_contract + .document_type_for_name(self.document_type_name.as_str()) + .map_err(ProtocolError::DataContractError) + } + + pub fn can_be_modified(&self) -> Result { + self.document_type() + .map(|document_type| document_type.documents_mutable()) + } + + pub fn requires_revision(&self) -> Result { + self.document_type() + .map(|document_type| document_type.requires_revision()) + } + + pub fn revision(&self) -> Option { + self.document.revision() + } + + /// Returns an optional block timestamp at which the document was created. + /// It will be None if it is not required by the schema. + pub fn created_at(&self) -> Option { + self.document.created_at() + } + + /// Returns an optional block timestamp at which the document was updated. + /// It will be None if it is not required by the schema. + pub fn updated_at(&self) -> Option { + self.document.updated_at() + } + + /// Returns an optional block height at which the document was created. + /// It will be None if it is not required by the schema. + pub fn created_at_block_height(&self) -> Option { + self.document.created_at_block_height() + } + + /// Returns an optional block height at which the document was last updated. + /// It will be None if it is not required by the schema. + pub fn updated_at_block_height(&self) -> Option { + self.document.updated_at_block_height() + } + + /// Returns an optional core block height at which the document was created. + /// It will be None if it is not required by the schema. + pub fn created_at_core_block_height(&self) -> Option { + self.document.created_at_core_block_height() + } + + /// Returns an optional core block height at which the document was last updated. + /// It will be None if it is not required by the schema. + pub fn updated_at_core_block_height(&self) -> Option { + self.document.updated_at_core_block_height() + } + + /// Create an extended document with additional information. + /// + /// # Arguments + /// + /// * `document` - A `Document` instance. + /// * `data_contract` - A `DataContract` instance. + /// * `document_type_name` - A `String` representing the document type name. + pub fn from_document_with_additional_info( + document: Document, + data_contract: DataContract, + document_type_name: String, + token_payment_info: Option + ) -> Self { + Self { + document_type_name, + data_contract_id: data_contract.id(), + document, + data_contract, + metadata: None, + entropy: Default::default(), + token_payment_info, + } + } + + #[cfg(feature = "document-json-conversion")] + /// Create an extended document from a JSON string. + /// + /// # Arguments + /// + /// * `string` - A JSON string representing the extended document. + /// * `contract` - A `DataContract` instance. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if there is an error decoding the JSON string. + pub fn from_json_string( + string: &str, + contract: DataContract, + platform_version: &PlatformVersion, + ) -> Result { + let json_value: JsonValue = serde_json::from_str(string).map_err(|_| { + ProtocolError::StringDecodeError("error decoding from json string".to_string()) + })?; + Self::from_untrusted_platform_value(json_value.into(), contract, platform_version) + } + + #[cfg(feature = "document-json-conversion")] + /// Create an extended document from a raw JSON document. + /// + /// # Arguments + /// + /// * `raw_document` - A `JsonValue` representing the raw document. + /// * `data_contract` - A `DataContract` instance. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if there is an error processing the raw JSON document. + pub fn from_raw_json_document( + raw_document: JsonValue, + data_contract: DataContract, + platform_version: &PlatformVersion, + ) -> Result { + Self::from_untrusted_platform_value(raw_document.into(), data_contract, platform_version) + } + + #[cfg(feature = "document-value-conversion")] + /// Create an extended document from a trusted platform value object where fields are already in + /// the proper format for the contract. + /// + /// # Arguments + /// + /// * `document_value` - A `Value` representing the document value. + /// * `data_contract` - A `DataContract` instance. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if there is an error processing the trusted platform value. + pub fn from_trusted_platform_value( + document_value: Value, + data_contract: DataContract, + platform_version: &PlatformVersion, + ) -> Result { + let mut properties = document_value + .clone() + .into_btree_string_map() + .map_err(ProtocolError::ValueError)?; + let document_type_name = properties + .remove_string(property_names::DOCUMENT_TYPE_NAME) + .map_err(ProtocolError::ValueError)?; + + let token_payment_info = properties + .remove_optional_map_as_btree_map_keep_values_as_platform_value( + property_names::TOKEN_PAYMENT_INFO, + ) + .ok() + .flatten().map(|map| map.try_into()).transpose()?; + + let document = Document::from_platform_value(document_value, platform_version)?; + + + let data_contract_id = data_contract.id(); + let mut extended_document = Self { + data_contract, + document_type_name, + document, + data_contract_id, + metadata: None, + entropy: Default::default(), + token_payment_info, + }; + + extended_document.data_contract_id = Identifier::new( + properties + .remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID)? + .unwrap_or(extended_document.data_contract.id().to_buffer()), + ); + Ok(extended_document) + } + + #[cfg(feature = "document-value-conversion")] + /// Create an extended document from an untrusted platform value object where fields might not + /// be in the proper format for the contract. + /// + /// # Arguments + /// + /// * `document_value` - A `Value` representing the document value. + /// * `data_contract` - A `DataContract` instance. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if there is an error processing the untrusted platform value. + pub fn from_untrusted_platform_value( + mut document_value: Value, + data_contract: DataContract, + platform_version: &PlatformVersion, + ) -> Result { + let mut properties = document_value + .clone() + .into_btree_string_map() + .map_err(ProtocolError::ValueError)?; + let document_type_name = properties + .remove_string(property_names::DOCUMENT_TYPE_NAME) + .map_err(ProtocolError::ValueError)?; + + let token_payment_info = properties + .remove_optional_map_as_btree_map_keep_values_as_platform_value( + property_names::TOKEN_PAYMENT_INFO, + ) + .ok() + .flatten().map(|map| map.try_into()).transpose()?; + + let document_type = data_contract.document_type_for_name(document_type_name.as_str())?; + + let identifiers = document_type.identifier_paths().to_owned(); + let binary_paths = document_type.binary_paths(); + + document_value.replace_at_paths(["$id", "$ownerId"], ReplacementType::Identifier)?; + document_value.replace_at_paths( + identifiers.iter().map(|s| s.as_str()), + ReplacementType::Identifier, + )?; + document_value.replace_at_paths( + binary_paths.iter().map(|s| s.as_str()), + ReplacementType::BinaryBytes, + )?; + + let document = Document::from_platform_value(document_value, platform_version)?; + let data_contract_id = data_contract.id(); + let mut extended_document = Self { + data_contract, + document_type_name, + document, + data_contract_id, + metadata: None, + entropy: Default::default(), + token_payment_info, + }; + + extended_document.data_contract_id = properties + .remove_optional_identifier(property_names::DATA_CONTRACT_ID)? + .unwrap_or(extended_document.data_contract.id()); + extended_document + .document + .properties_mut() + .replace_at_paths(&identifiers, ReplacementType::Identifier)?; + Ok(extended_document) + } + + #[cfg(feature = "document-json-conversion")] + /// Convert the extended document to a pretty JSON object. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if there is an error converting the document to pretty JSON. + pub fn to_pretty_json( + &self, + platform_version: &PlatformVersion, + ) -> Result { + let mut value = self.document.to_json(platform_version)?; + let value_mut = value.as_object_mut().unwrap(); + value_mut.insert( + property_names::DOCUMENT_TYPE_NAME.to_string(), + JsonValue::String(self.document_type_name.clone()), + ); + value_mut.insert( + property_names::DATA_CONTRACT_ID.to_string(), + JsonValue::String(bs58::encode(self.data_contract_id.to_buffer()).into_string()), + ); + if let Some(token_payment_info) = self.token_payment_info { + value_mut.insert( + property_names::TOKEN_PAYMENT_INFO.to_string(), + token_payment_info.into(), + ); + } + Ok(value) + } + + #[cfg(feature = "document-value-conversion")] + pub fn to_map_value(&self) -> Result, ProtocolError> { + let mut object = self.document.to_map_value()?; + object.insert( + property_names::DOCUMENT_TYPE_NAME.to_string(), + Value::Text(self.document_type_name.clone()), + ); + object.insert( + property_names::DATA_CONTRACT_ID.to_string(), + Value::Identifier(self.data_contract_id.to_buffer()), + ); + if let Some(token_payment_info) = self.token_payment_info { + object.insert( + property_names::TOKEN_PAYMENT_INFO.to_string(), + token_payment_info.into(), + ); + } + Ok(object) + } + + #[cfg(feature = "document-value-conversion")] + pub fn into_map_value(self) -> Result, ProtocolError> { + let ExtendedDocumentV1 { + document_type_name, + data_contract_id, + document, + token_payment_info, + .. + } = self; + + let mut object = document.into_map_value()?; + object.insert(property_names::FEATURE_VERSION.to_string(), Value::U16(0)); + object.insert( + property_names::DOCUMENT_TYPE_NAME.to_string(), + Value::Text(document_type_name), + ); + object.insert( + property_names::DATA_CONTRACT_ID.to_string(), + Value::Identifier(data_contract_id.to_buffer()), + ); + if let Some(token_payment_info) = token_payment_info { + object.insert( + property_names::TOKEN_PAYMENT_INFO.to_string(), + token_payment_info.into(), + ); + } + Ok(object) + } + + #[cfg(feature = "document-value-conversion")] + pub fn into_value(self) -> Result { + Ok(self.into_map_value()?.into()) + } + + #[cfg(feature = "document-value-conversion")] + pub fn to_value(&self) -> Result { + Ok(self.to_map_value()?.into()) + } + + #[cfg(feature = "document-json-conversion")] + pub fn to_json_object_for_validation(&self) -> Result { + self.to_value()? + .try_into_validating_json() + .map_err(ProtocolError::ValueError) + } + + pub fn hash(&self, platform_version: &PlatformVersion) -> Result, ProtocolError> { + Ok(hash_double_to_vec( + ExtendedDocumentPlatformConversionMethodsV0::serialize_to_bytes( + self, + platform_version, + )?, + )) + } + + /// Set the value under given path. + /// The path supports syntax from `lodash` JS lib. Example: "root.people[0].name". + /// If parents are not present they will be automatically created + pub fn set(&mut self, path: &str, value: Value) -> Result<(), ProtocolError> { + Ok(self.document.properties_mut().insert_at_path(path, value)?) + } + + /// Set the value under given path. + /// The path supports syntax from `lodash` JS lib. Example: "root.people[0].name". + /// If parents are not present they will be automatically created + pub fn set_untrusted(&mut self, path: &str, value: Value) -> Result<(), ProtocolError> { + let document_type = self.document_type()?; + + let identifiers = document_type.identifier_paths(); + let binary_paths = document_type.binary_paths(); + + if identifiers.contains(path) { + let value = + ReplacementType::Identifier.replace_for_bytes(value.to_identifier_bytes()?)?; + self.set(path, value) + } else if binary_paths.contains(path) { + let value = + ReplacementType::BinaryBytes.replace_for_bytes(value.to_identifier_bytes()?)?; + self.set(path, value) + } else { + self.set(path, value) + } + } + + /// Retrieves field specified by path + pub fn get(&self, path: &str) -> Option<&Value> { + self.properties().get_optional_at_path(path).ok().flatten() + } + + // TODO: We probably should validate extended document on creation and during modification + // instead of have a dedicated method. That would be more Rust way approach + #[cfg(feature = "validation")] + /// Validate external document + pub fn validate( + &self, + platform_version: &PlatformVersion, + ) -> Result { + self.data_contract.validate_document( + &self.document_type_name, + &self.document, + platform_version, + ) + } +} diff --git a/packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs b/packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs new file mode 100644 index 00000000000..a27f8f7ea45 --- /dev/null +++ b/packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs @@ -0,0 +1,77 @@ +use crate::document::extended_document::v0::ExtendedDocumentV0; +use crate::document::property_names; +use crate::document::serialization_traits::DocumentPlatformValueMethodsV0; +use crate::version::PlatformVersion; +use crate::ProtocolError; + +use platform_value::Value; +use std::collections::BTreeMap; + +impl DocumentPlatformValueMethodsV0<'_> for ExtendedDocumentV0 { + fn to_map_value(&self) -> Result, ProtocolError> { + let mut map: BTreeMap = BTreeMap::new(); + map.insert(property_names::ID.to_string(), self.id().into()); + map.insert(property_names::OWNER_ID.to_string(), self.owner_id().into()); + + if let Some(created_at) = self.created_at() { + map.insert( + property_names::CREATED_AT.to_string(), + Value::U64(created_at), + ); + } + if let Some(updated_at) = self.updated_at() { + map.insert( + property_names::UPDATED_AT.to_string(), + Value::U64(updated_at), + ); + } + if let Some(revision) = self.revision() { + map.insert(property_names::REVISION.to_string(), Value::U64(revision)); + } + + map.extend(self.properties().clone()); + + Ok(map) + } + + fn into_map_value(self) -> Result, ProtocolError> { + let mut map: BTreeMap = BTreeMap::new(); + map.insert(property_names::ID.to_string(), self.id().into()); + map.insert(property_names::OWNER_ID.to_string(), self.owner_id().into()); + + if let Some(created_at) = self.created_at() { + map.insert( + property_names::CREATED_AT.to_string(), + Value::U64(created_at), + ); + } + if let Some(updated_at) = self.updated_at() { + map.insert( + property_names::UPDATED_AT.to_string(), + Value::U64(updated_at), + ); + } + if let Some(revision) = self.revision() { + map.insert(property_names::REVISION.to_string(), Value::U64(revision)); + } + + map.extend(self.properties().to_owned()); + + Ok(map) + } + + fn into_value(self) -> Result { + Ok(self.into_map_value()?.into()) + } + + fn to_object(&self) -> Result { + Ok(self.to_map_value()?.into()) + } + + fn from_platform_value( + document_value: Value, + _platform_version: &PlatformVersion, + ) -> Result { + Ok(platform_value::from_value(document_value)?) + } +} diff --git a/packages/rs-dpp/src/document/extended_document/v1/serialize.rs b/packages/rs-dpp/src/document/extended_document/v1/serialize.rs new file mode 100644 index 00000000000..255d49bd960 --- /dev/null +++ b/packages/rs-dpp/src/document/extended_document/v1/serialize.rs @@ -0,0 +1,213 @@ +use crate::document::Document; + +use crate::prelude::DataContract; + +use crate::ProtocolError; + +use crate::data_contract::accessors::v0::DataContractV0Getters; + +use crate::document::extended_document::v0::ExtendedDocumentV0; +use crate::document::serialization_traits::deserialize::v0::ExtendedDocumentPlatformDeserializationMethodsV0; +use crate::document::serialization_traits::serialize::v0::ExtendedDocumentPlatformSerializationMethodsV0; +use crate::document::serialization_traits::{ + DocumentPlatformConversionMethodsV0, ExtendedDocumentPlatformConversionMethodsV0, +}; + +use crate::serialization::{ + PlatformDeserializableWithBytesLenFromVersionedStructure, + PlatformSerializableWithPlatformVersion, +}; +use crate::version::PlatformVersion; + +use integer_encoding::{VarInt, VarIntReader}; + +use crate::consensus::basic::decode::DecodingError; +use crate::data_contract::errors::DataContractError; +use platform_version::version::FeatureVersion; + +impl ExtendedDocumentPlatformSerializationMethodsV0 for ExtendedDocumentV0 { + /// Serializes the extended document. + /// + /// The serialization of an extended document follows the pattern: + /// data contract | document type name | document + fn serialize_v0(&self, platform_version: &PlatformVersion) -> Result, ProtocolError> { + let mut buffer: Vec = 0.encode_var_vec(); //version 0 + + buffer.append( + &mut self + .data_contract + .serialize_to_bytes_with_platform_version(platform_version)?, + ); + buffer.push(self.document_type_name.len() as u8); + buffer.extend(self.document_type_name.as_bytes()); + buffer.append( + &mut self + .document + .serialize(self.document_type()?, platform_version)?, + ); + Ok(buffer) + } + + /// Serializes the extended document. + /// + /// The serialization of an extended document follows the pattern: + /// data contract | document type name | document + fn serialize_consume_v0( + self, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError> { + let ExtendedDocumentV0 { + document_type_name, + document, + data_contract, + .. + } = self; + + let mut serialized_document = document.serialize_consume( + data_contract.document_type_for_name(document_type_name.as_str())?, + platform_version, + )?; + + let mut buffer: Vec = 0.encode_var_vec(); //version 0 + + buffer.append( + &mut data_contract + .serialize_consume_to_bytes_with_platform_version(platform_version)?, + ); + buffer.push(document_type_name.len() as u8); + buffer.append(&mut document_type_name.into_bytes()); + buffer.append(&mut serialized_document); + Ok(buffer) + } +} + +impl ExtendedDocumentPlatformDeserializationMethodsV0 for ExtendedDocumentV0 { + /// Reads a serialized document and creates a Document from it. + fn from_bytes_v0( + serialized_extended_document: &[u8], + platform_version: &PlatformVersion, + ) -> Result { + // first we deserialize the contract + let (data_contract, offset) = DataContract::versioned_deserialize_with_bytes_len( + serialized_extended_document, + true, //since this would only happen on the client, we should validate + platform_version, + )?; + let serialized_document = serialized_extended_document.split_at(offset).1; + let (document_type_name_len, rest) = + serialized_document + .split_first() + .ok_or(DataContractError::DecodingDocumentError( + DecodingError::new( + "error reading document type name len from serialized extended document" + .to_string(), + ), + ))?; + if serialized_document.len() < *document_type_name_len as usize { + return Err(ProtocolError::DecodingError( + "serialized extended document isn't big enough for the document type len" + .to_string(), + )); + } + let (document_type_name_bytes, rest) = rest.split_at(*document_type_name_len as usize); + let document_type_name = String::from_utf8(document_type_name_bytes.into()) + .map_err(|e| ProtocolError::DecodingError(e.to_string()))?; + + let document_type = data_contract.document_type_for_name(document_type_name.as_str())?; + + let document = Document::from_bytes(rest, document_type, platform_version)?; + + Ok(ExtendedDocumentV0 { + document_type_name, + data_contract_id: data_contract.id(), + document, + data_contract, + metadata: None, + + entropy: Default::default(), + }) + } +} + +impl ExtendedDocumentPlatformConversionMethodsV0 for ExtendedDocumentV0 { + /// Serializes the document. + /// + /// The serialization of a document follows the pattern: + /// id 32 bytes + owner_id 32 bytes + encoded values byte arrays + fn serialize_to_bytes( + &self, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError> { + match platform_version + .dpp + .document_versions + .document_serialization_version + .default_current_version + { + 0 => self.serialize_v0(platform_version), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "ExtendedDocumentV0::serialize".to_string(), + known_versions: vec![0], + received: version, + }), + } + } + + fn serialize_specific_version_to_bytes( + &self, + feature_version: FeatureVersion, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError> { + match feature_version { + 0 => self.serialize_v0(platform_version), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "ExtendedDocumentV0::serialize".to_string(), + known_versions: vec![0], + received: version, + }), + } + } + + /// Serializes and consumes the document. + /// + /// The serialization of a document follows the pattern: + /// id 32 bytes + owner_id 32 bytes + encoded values byte arrays + fn serialize_consume_to_bytes( + self, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError> { + match platform_version + .dpp + .contract_versions + .contract_serialization_version + .default_current_version + { + 0 => self.serialize_consume_v0(platform_version), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "DocumentV0::serialize_consume".to_string(), + known_versions: vec![0], + received: version, + }), + } + } + + /// Reads a serialized document and creates an ExtendedDocumentV0 from it. + fn from_bytes( + mut serialized_document: &[u8], + platform_version: &PlatformVersion, + ) -> Result { + let serialized_version = serialized_document.read_varint().map_err(|_| { + ProtocolError::DecodingError( + "error reading revision from serialized document for revision".to_string(), + ) + })?; + match serialized_version { + 0 => ExtendedDocumentV0::from_bytes_v0(serialized_document, platform_version), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "ExtendedDocument::from_bytes (deserialization)".to_string(), + known_versions: vec![0], + received: version, + }), + } + } +} diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 5a0478ad24b..ea0ef520884 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -250,6 +250,8 @@ impl ErrorWithCode for StateError { Self::DocumentContestIdentityAlreadyContestantError(_) => 40112, Self::DocumentContestDocumentWithSameIdAlreadyPresentError(_) => 40113, Self::DocumentContestNotPaidForError(_) => 40114, + Self::RequiredTokenPaymentInfoNotSetError(_) => 40115, + Self::IdentityHasNotAgreedToPayRequiredTokenAmountError(_) => 40116, // Identity Errors: 40200-40299 Self::IdentityAlreadyExistsError(_) => 40200, diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 9e358de2df7..4b6b74f4d28 100644 --- a/packages/rs-dpp/src/errors/protocol_error.rs +++ b/packages/rs-dpp/src/errors/protocol_error.rs @@ -284,6 +284,9 @@ pub enum ProtocolError { #[error("missing epoch info: {0}")] MissingEpochInfo(String), + + #[error("Invalid BatchedTransitionAction variant: expected {expected}, found {found}")] + InvalidBatchedTransitionActionVariant { expected: &'static str, found: &'static str }, } impl From<&str> for ProtocolError { diff --git a/packages/rs-dpp/src/state_transition/serialization.rs b/packages/rs-dpp/src/state_transition/serialization.rs index ff55d2653ab..998c0e017c7 100644 --- a/packages/rs-dpp/src/state_transition/serialization.rs +++ b/packages/rs-dpp/src/state_transition/serialization.rs @@ -335,6 +335,7 @@ mod tests { .document_type_for_name(extended_document.document_type_name()) .unwrap(), *extended_document.entropy(), + None, ) }) .collect::>(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs index 2ec96911633..6448ab3c8cd 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs @@ -187,7 +187,7 @@ mod test { let result = create_contact_request_data_trigger( &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { Ok(Arc::new(DataContractFetchInfo::dashpay_contract_fixture(protocol_version))) - }, platform_version).expect("expected to create action").0.into(), + }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, platform_version, ) @@ -310,7 +310,7 @@ mod test { let result = create_contact_request_data_trigger( &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { Ok(Arc::new(DataContractFetchInfo::dashpay_contract_fixture(protocol_version))) - }, platform_version).expect("expected to create action").0.into(), + }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, platform_version, ) @@ -428,7 +428,7 @@ mod test { let result = create_contact_request_data_trigger( &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { Ok(Arc::new(DataContractFetchInfo::dashpay_contract_fixture(protocol_version))) - }, platform_version).expect("expected to create action").0.into(), + }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, platform_version, ) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs index abbc3267b8f..495786d8b60 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs @@ -448,7 +448,7 @@ mod test { &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { Ok(Arc::new(DataContractFetchInfo::dpns_contract_fixture(platform_version.protocol_version))) - }, platform_version).expect("expected to create action").0.into(), + }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, platform_version, ) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs index 7ed136e6e2c..182201eae87 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs @@ -626,11 +626,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { execution_context .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); - - let batched_action = BatchedTransitionAction::DocumentAction( - DocumentTransitionAction::CreateAction(document_create_action), - ); - Ok(batched_action.into()) + Ok(document_create_action) } DocumentTransition::Replace(document_replace_transition) => { let mut result = ConsensusValidationResult::::new(); @@ -702,7 +698,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { } } - let document_replace_action = + let (document_replace_action, fee_result) = DocumentReplaceTransitionAction::try_from_borrowed_document_replace_transition( document_replace_transition, original_document_created_at, @@ -715,23 +711,24 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { |_identifier| Ok(data_contract_fetch_info.clone()), )?; + execution_context + .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + if result.is_valid() { - let batched_action = BatchedTransitionAction::DocumentAction( - DocumentTransitionAction::ReplaceAction(document_replace_action), - ); - Ok(batched_action.into()) + Ok(document_replace_action) } else { Ok(result) } } DocumentTransition::Delete(document_delete_transition) => { - let action = DocumentDeleteTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(document_delete_transition, |_identifier| { + let (batched_action, fee_result) = DocumentDeleteTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(document_delete_transition, |_identifier| { Ok(data_contract_fetch_info.clone()) })?; - let batched_action = BatchedTransitionAction::DocumentAction( - DocumentTransitionAction::DeleteAction(action), - ); - Ok(batched_action.into()) + + execution_context + .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + + Ok(batched_action) } DocumentTransition::Transfer(document_transfer_transition) => { let mut result = ConsensusValidationResult::::new(); @@ -773,7 +770,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { } } - let document_transfer_action = + let (document_transfer_action, fee_result) = DocumentTransferTransitionAction::try_from_borrowed_document_transfer_transition( document_transfer_transition, original_document.clone(), //todo: remove clone @@ -781,11 +778,11 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { |_identifier| Ok(data_contract_fetch_info.clone()), )?; + execution_context + .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + if result.is_valid() { - let batched_action = BatchedTransitionAction::DocumentAction( - DocumentTransitionAction::TransferAction(document_transfer_action), - ); - Ok(batched_action.into()) + Ok(document_transfer_action) } else { Ok(result) } @@ -830,7 +827,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { } } - let document_update_price_action = + let (document_update_price_action, fee_result) = DocumentUpdatePriceTransitionAction::try_from_borrowed_document_update_price_transition( document_update_price_transition, original_document.clone(), //todo: find a way to not have to use cloning @@ -838,11 +835,11 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { |_identifier| Ok(data_contract_fetch_info.clone()), )?; + execution_context + .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + if result.is_valid() { - let batched_action = BatchedTransitionAction::DocumentAction( - DocumentTransitionAction::UpdatePriceAction(document_update_price_action), - ); - Ok(batched_action.into()) + Ok(document_update_price_action) } else { Ok(result) } @@ -897,7 +894,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { } } - let document_purchase_action = + let (document_purchase_action, fee_result) = DocumentPurchaseTransitionAction::try_from_borrowed_document_purchase_transition( document_purchase_transition, original_document.clone(), //todo: find a way to not have to use cloning @@ -906,11 +903,11 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { |_identifier| Ok(data_contract_fetch_info.clone()), )?; + execution_context + .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + if result.is_valid() { - let batched_action = BatchedTransitionAction::DocumentAction( - DocumentTransitionAction::PurchaseAction(document_purchase_action), - ); - Ok(batched_action.into()) + Ok(document_purchase_action) } else { Ok(result) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs index dab39d6d725..f1a3698fb57 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs @@ -3,13 +3,14 @@ use dpp::fee::fee_result::FeeResult; use dpp::platform_value::Identifier; use grovedb::TransactionArg; use std::sync::Arc; - +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_create_transition::DocumentCreateTransition; use platform_version::version::PlatformVersion; use crate::drive::contract::DataContractFetchInfo; use crate::drive::Drive; use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::{DocumentCreateTransitionAction, DocumentCreateTransitionActionV0}; impl DocumentCreateTransitionAction { @@ -21,11 +22,16 @@ impl DocumentCreateTransitionAction { block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, - ) -> Result<(Self, FeeResult), Error> { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match value { DocumentCreateTransition::V0(v0) => { - let (v0, fee) = DocumentCreateTransitionActionV0::try_from_document_create_transition_with_contract_lookup(drive, transaction, v0, block_info, get_data_contract, platform_version)?; - Ok((v0.into(), fee)) + DocumentCreateTransitionActionV0::try_from_document_create_transition_with_contract_lookup(drive, transaction, v0, block_info, get_data_contract, platform_version) } } } @@ -38,11 +44,16 @@ impl DocumentCreateTransitionAction { block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, - ) -> Result<(Self, FeeResult), Error> { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match value { DocumentCreateTransition::V0(v0) => { - let (v0, fee) = DocumentCreateTransitionActionV0::try_from_borrowed_document_create_transition_with_contract_lookup(drive, transaction, v0, block_info, get_data_contract, platform_version)?; - Ok((v0.into(), fee)) + DocumentCreateTransitionActionV0::try_from_borrowed_document_create_transition_with_contract_lookup(drive, transaction, v0, block_info, get_data_contract, platform_version) } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs index 0d54449e5b2..356918c118e 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs @@ -4,7 +4,7 @@ use dpp::fee::fee_result::FeeResult; use dpp::platform_value::Identifier; use grovedb::TransactionArg; use std::sync::Arc; - +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_create_transition::v0::DocumentCreateTransitionV0; use dpp::voting::vote_info_storage::contested_document_vote_poll_stored_info::ContestedDocumentVotePollStoredInfo; @@ -15,8 +15,10 @@ use crate::drive::Drive; use crate::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::resolve::ContestedDocumentResourceVotePollResolver; use crate::error::drive::DriveError; use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; use crate::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionActionV0; +use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; impl DocumentCreateTransitionActionV0 { /// try from document create transition with contract lookup @@ -27,7 +29,13 @@ impl DocumentCreateTransitionActionV0 { block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, - ) -> Result<(Self, FeeResult), Error> { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentCreateTransitionV0 { base, data, @@ -103,14 +111,18 @@ impl DocumentCreateTransitionActionV0 { }; Ok(( - DocumentCreateTransitionActionV0 { - base, - block_info: *block_info, - data, - prefunded_voting_balance: prefunded_voting_balances_by_vote_poll, - current_store_contest_info, - should_store_contest_info, - }, + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::CreateAction( + DocumentCreateTransitionActionV0 { + base, + block_info: *block_info, + data, + prefunded_voting_balance: prefunded_voting_balances_by_vote_poll, + current_store_contest_info, + should_store_contest_info, + } + .into(), + )) + .into(), fee_result, )) } @@ -123,7 +135,13 @@ impl DocumentCreateTransitionActionV0 { block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, - ) -> Result<(Self, FeeResult), Error> { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentCreateTransitionV0 { base, data, @@ -201,14 +219,18 @@ impl DocumentCreateTransitionActionV0 { }; Ok(( - DocumentCreateTransitionActionV0 { - base, - block_info: *block_info, - data: data.clone(), - prefunded_voting_balance: prefunded_voting_balances_by_vote_poll, - current_store_contest_info, - should_store_contest_info, - }, + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::CreateAction( + DocumentCreateTransitionActionV0 { + base, + block_info: *block_info, + data: data.clone(), + prefunded_voting_balance: prefunded_voting_balances_by_vote_poll, + current_store_contest_info, + should_store_contest_info, + } + .into(), + )) + .into(), fee_result, )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs index ede80bd6f0b..ce33289bb79 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs @@ -1,9 +1,12 @@ use dpp::platform_value::Identifier; use std::sync::Arc; - +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentDeleteTransition; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::{DocumentDeleteTransitionAction, DocumentDeleteTransitionActionV0}; impl DocumentDeleteTransitionAction { @@ -11,9 +14,15 @@ impl DocumentDeleteTransitionAction { pub fn try_from_document_create_transition_with_contract_lookup( value: DocumentDeleteTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match value { - DocumentDeleteTransition::V0(v0) => Ok(DocumentDeleteTransitionActionV0::try_from_document_delete_transition_with_contract_lookup(v0, get_data_contract)?.into()), + DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_document_delete_transition_with_contract_lookup(v0, get_data_contract), } } @@ -21,9 +30,15 @@ impl DocumentDeleteTransitionAction { pub fn try_from_document_borrowed_create_transition_with_contract_lookup( value: &DocumentDeleteTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match value { - DocumentDeleteTransition::V0(v0) => Ok(DocumentDeleteTransitionActionV0::try_from_borrowed_document_delete_transition_with_contract_lookup(v0, get_data_contract)?.into()), + DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_borrowed_document_delete_transition_with_contract_lookup(v0, get_data_contract), } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs index 33e9f5ec023..28bca387c52 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs @@ -1,42 +1,74 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_delete_transition::DocumentDeleteTransitionV0; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::v0::DocumentDeleteTransitionActionV0; +use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; impl DocumentDeleteTransitionActionV0 { /// try from pub fn try_from_document_delete_transition_with_contract_lookup( value: DocumentDeleteTransitionV0, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentDeleteTransitionV0 { base, .. } = value; - Ok(DocumentDeleteTransitionActionV0 { - base: DocumentBaseTransitionAction::try_from_base_transition_with_contract_lookup( - base, - get_data_contract, - |document_type| document_type.document_deletion_token_cost(), - )?, - }) + + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::DeleteAction( + DocumentDeleteTransitionActionV0 { + base: DocumentBaseTransitionAction::try_from_base_transition_with_contract_lookup( + base, + get_data_contract, + |document_type| document_type.document_deletion_token_cost(), + )? + } + + .into(), + )) + .into(), + FeeResult::default(), + )) } /// try from borrowed pub fn try_from_borrowed_document_delete_transition_with_contract_lookup( value: &DocumentDeleteTransitionV0, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentDeleteTransitionV0 { base, .. } = value; - Ok(DocumentDeleteTransitionActionV0 { - base: DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( - base, - get_data_contract, - |document_type| { - document_type.document_deletion_token_cost() + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::DeleteAction( + DocumentDeleteTransitionActionV0 { + base: DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( + base, + get_data_contract, + |document_type| document_type.document_deletion_token_cost(), + )? } - )?, - }) + + .into(), + )) + .into(), + FeeResult::default(), + )) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs index 7f591c601f6..1c300c8d661 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs @@ -2,10 +2,13 @@ use dpp::block::block_info::BlockInfo; use dpp::document::Document; use dpp::platform_value::Identifier; use std::sync::Arc; - +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentPurchaseTransition; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_purchase_transition_action::{DocumentPurchaseTransitionAction, DocumentPurchaseTransitionActionV0}; impl DocumentPurchaseTransitionAction { @@ -16,18 +19,22 @@ impl DocumentPurchaseTransitionAction { purchaser_id: Identifier, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match document_purchase_transition { - DocumentPurchaseTransition::V0(v0) => Ok( + DocumentPurchaseTransition::V0(v0) => DocumentPurchaseTransitionActionV0::try_from_borrowed_document_purchase_transition( v0, original_document, purchaser_id, block_info, get_data_contract, - )? - .into(), - ), + ), } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs index b9380c6b48d..1fa1fc1275c 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs @@ -4,11 +4,16 @@ use dpp::document::{property_names, Document, DocumentV0Getters, DocumentV0Sette use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_purchase_transition::DocumentPurchaseTransitionV0; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_purchase_transition_action::v0::DocumentPurchaseTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; +use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; impl DocumentPurchaseTransitionActionV0 { /// try from borrowed @@ -18,7 +23,13 @@ impl DocumentPurchaseTransitionActionV0 { purchaser_id: Identifier, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentPurchaseTransitionV0 { base, price, .. } = document_purchase_transition; let base = DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( @@ -50,11 +61,18 @@ impl DocumentPurchaseTransitionActionV0 { modified_document.set_transferred_at_core_block_height(Some(block_info.core_height)); } - Ok(DocumentPurchaseTransitionActionV0 { - base, - document: modified_document, - original_owner_id, - price: *price, - }) + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::PurchaseAction( + DocumentPurchaseTransitionActionV0 { + base, + document: modified_document, + original_owner_id, + price: *price, + } + .into(), + )) + .into(), + FeeResult::default(), + )) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs index 51f52bd4e6e..1762391d93b 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs @@ -1,12 +1,14 @@ use dpp::block::block_info::BlockInfo; use dpp::platform_value::Identifier; use std::sync::Arc; - +use dpp::fee::fee_result::FeeResult; use dpp::identity::TimestampMillis; -use dpp::prelude::{BlockHeight, CoreBlockHeight}; +use dpp::prelude::{BlockHeight, ConsensusValidationResult, CoreBlockHeight}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentReplaceTransition; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_replace_transition_action::{DocumentReplaceTransitionAction, DocumentReplaceTransitionActionV0}; impl DocumentReplaceTransitionAction { @@ -21,9 +23,15 @@ impl DocumentReplaceTransitionAction { originally_transferred_at_core_block_height: Option, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match document_replace_transition { - DocumentReplaceTransition::V0(v0) => Ok( + DocumentReplaceTransition::V0(v0) => DocumentReplaceTransitionActionV0::try_from_borrowed_document_replace_transition( v0, originally_created_at, @@ -34,9 +42,7 @@ impl DocumentReplaceTransitionAction { originally_transferred_at_core_block_height, block_info, get_data_contract, - )? - .into(), - ), + ), } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs index d3148b21486..3e0ae2ada2a 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs @@ -3,13 +3,17 @@ use dpp::document::property_names; use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; +use dpp::fee::fee_result::FeeResult; use dpp::identity::TimestampMillis; -use dpp::prelude::{BlockHeight, CoreBlockHeight}; +use dpp::prelude::{BlockHeight, ConsensusValidationResult, CoreBlockHeight}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_replace_transition::DocumentReplaceTransitionV0; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_replace_transition_action::v0::DocumentReplaceTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; +use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; impl DocumentReplaceTransitionActionV0 { /// try from borrowed @@ -23,7 +27,13 @@ impl DocumentReplaceTransitionActionV0 { originally_transferred_at_core_block_height: Option, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentReplaceTransitionV0 { base, revision, @@ -57,19 +67,26 @@ impl DocumentReplaceTransitionActionV0 { None }; - Ok(DocumentReplaceTransitionActionV0 { - base, - revision: *revision, - created_at: originally_created_at, - updated_at, - transferred_at: originally_transferred_at, - created_at_block_height: originally_created_at_block_height, - updated_at_block_height, - transferred_at_block_height: originally_transferred_at_block_height, - created_at_core_block_height: originally_created_at_core_block_height, - updated_at_core_block_height, - transferred_at_core_block_height: originally_transferred_at_core_block_height, - data: data.clone(), - }) + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::ReplaceAction( + DocumentReplaceTransitionActionV0 { + base, + revision: *revision, + created_at: originally_created_at, + updated_at, + transferred_at: originally_transferred_at, + created_at_block_height: originally_created_at_block_height, + updated_at_block_height, + transferred_at_block_height: originally_transferred_at_block_height, + created_at_core_block_height: originally_created_at_core_block_height, + updated_at_core_block_height, + transferred_at_core_block_height: originally_transferred_at_core_block_height, + data: data.clone(), + } + .into(), + )) + .into(), + FeeResult::default(), + )) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs index 736d414f17c..b7495b8fecb 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs @@ -2,10 +2,13 @@ use dpp::block::block_info::BlockInfo; use dpp::document::Document; use dpp::platform_value::Identifier; use std::sync::Arc; - +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentTransferTransition; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_transfer_transition_action::{DocumentTransferTransitionAction, DocumentTransferTransitionActionV0}; impl DocumentTransferTransitionAction { @@ -15,17 +18,20 @@ impl DocumentTransferTransitionAction { original_document: Document, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match document_transfer_transition { - DocumentTransferTransition::V0(v0) => Ok( - DocumentTransferTransitionActionV0::try_from_borrowed_document_transfer_transition( + DocumentTransferTransition::V0(v0) => DocumentTransferTransitionActionV0::try_from_borrowed_document_transfer_transition( v0, original_document, block_info, get_data_contract, - )? - .into(), - ), + ), } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs index 6103bfe58f0..9d4fafaa4fa 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs @@ -4,11 +4,16 @@ use dpp::document::{property_names, Document, DocumentV0Getters, DocumentV0Sette use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_transfer_transition::DocumentTransferTransitionV0; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_transfer_transition_action::v0::DocumentTransferTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; +use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; impl DocumentTransferTransitionActionV0 { /// try from borrowed @@ -17,7 +22,13 @@ impl DocumentTransferTransitionActionV0 { original_document: Document, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentTransferTransitionV0 { base, recipient_owner_id, @@ -51,9 +62,16 @@ impl DocumentTransferTransitionActionV0 { modified_document.set_transferred_at_core_block_height(Some(block_info.core_height)); } - Ok(DocumentTransferTransitionActionV0 { - base, - document: modified_document, - }) + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::TransferAction( + DocumentTransferTransitionActionV0 { + base, + document: modified_document, + } + .into(), + )) + .into(), + FeeResult::default(), + )) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs index 524ff7e6c1a..0d5f94b0111 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs @@ -2,10 +2,13 @@ use dpp::block::block_info::BlockInfo; use dpp::document::Document; use dpp::platform_value::Identifier; use std::sync::Arc; - +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentUpdatePriceTransition; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_update_price_transition_action::{DocumentUpdatePriceTransitionAction, DocumentUpdatePriceTransitionActionV0}; impl DocumentUpdatePriceTransitionAction { @@ -15,17 +18,20 @@ impl DocumentUpdatePriceTransitionAction { original_document: Document, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { match document_update_price_transition { - DocumentUpdatePriceTransition::V0(v0) => Ok( - DocumentUpdatePriceTransitionActionV0::try_from_borrowed_document_update_price_transition( + DocumentUpdatePriceTransition::V0(v0) => DocumentUpdatePriceTransitionActionV0::try_from_borrowed_document_update_price_transition( v0, original_document, block_info, get_data_contract, - )? - .into(), - ), + ), } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs index ffe82035d3f..217a8e1ee63 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs @@ -4,11 +4,16 @@ use dpp::document::{property_names, Document, DocumentV0Setters}; use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; +use dpp::fee::fee_result::FeeResult; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_update_price_transition::DocumentUpdatePriceTransitionV0; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; +use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_update_price_transition_action::v0::DocumentUpdatePriceTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; +use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; impl DocumentUpdatePriceTransitionActionV0 { /// try from borrowed @@ -17,7 +22,13 @@ impl DocumentUpdatePriceTransitionActionV0 { original_document: Document, block_info: &BlockInfo, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result { + ) -> Result< + ( + ConsensusValidationResult, + FeeResult, + ), + Error, + > { let DocumentUpdatePriceTransitionV0 { base, price, .. } = document_update_price_transition; let base = DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( @@ -44,9 +55,16 @@ impl DocumentUpdatePriceTransitionActionV0 { modified_document.set_updated_at_core_block_height(Some(block_info.core_height)); } - Ok(DocumentUpdatePriceTransitionActionV0 { - base, - document: modified_document, - }) + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::UpdatePriceAction( + DocumentUpdatePriceTransitionActionV0 { + base, + document: modified_document, + } + .into(), + )) + .into(), + FeeResult::default(), + )) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs index 4ba839bd84f..0286df9c402 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs @@ -1,5 +1,6 @@ use derive_more::From; use dpp::identifier::Identifier; +use dpp::ProtocolError; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::TokenBaseTransitionActionAccessorsV0; @@ -37,4 +38,46 @@ impl BatchedTransitionAction { } } } + /// as_document_action + pub fn as_document_action(&self) -> Result<&DocumentTransitionAction, ProtocolError> { + match self { + BatchedTransitionAction::DocumentAction(action) => Ok(action), + other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { + expected: "DocumentAction", + found: other.variant_name(), + }), + } + } + + /// as_token_action + pub fn as_token_action(&self) -> Result<&TokenTransitionAction, ProtocolError> { + match self { + BatchedTransitionAction::TokenAction(action) => Ok(action), + other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { + expected: "TokenAction", + found: other.variant_name(), + }), + } + } + + /// as_bump_identity_nonce_action + + pub fn as_bump_identity_nonce_action(&self) -> Result<&BumpIdentityDataContractNonceAction, ProtocolError> { + match self { + BatchedTransitionAction::BumpIdentityDataContractNonce(action) => Ok(action), + other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { + expected: "BumpIdentityDataContractNonce", + found: other.variant_name(), + }), + } + } + + /// Helper method to get the variant name for diagnostics. + fn variant_name(&self) -> &'static str { + match self { + BatchedTransitionAction::DocumentAction(_) => "DocumentAction", + BatchedTransitionAction::TokenAction(_) => "TokenAction", + BatchedTransitionAction::BumpIdentityDataContractNonce(_) => "BumpIdentityDataContractNonce", + } + } } diff --git a/packages/rs-sdk/src/platform/transition/purchase_document.rs b/packages/rs-sdk/src/platform/transition/purchase_document.rs index 8423bd66d05..5ba94ef7d5f 100644 --- a/packages/rs-sdk/src/platform/transition/purchase_document.rs +++ b/packages/rs-sdk/src/platform/transition/purchase_document.rs @@ -12,6 +12,7 @@ use dpp::prelude::Identifier; use dpp::state_transition::batch_transition::methods::v0::DocumentsBatchTransitionMethodsV0; use dpp::state_transition::batch_transition::BatchTransition; use dpp::state_transition::StateTransition; +use dpp::tokens::token_payment_info::TokenPaymentInfo; #[async_trait::async_trait] /// A trait for purchasing a document on Platform @@ -25,6 +26,7 @@ pub trait PurchaseDocument: Waitable { document_type: DocumentType, purchaser_id: Identifier, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result; @@ -37,6 +39,7 @@ pub trait PurchaseDocument: Waitable { document_type: DocumentType, purchaser_id: Identifier, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result; @@ -51,6 +54,7 @@ impl PurchaseDocument for Document { document_type: DocumentType, purchaser_id: Identifier, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result { @@ -73,6 +77,7 @@ impl PurchaseDocument for Document { &identity_public_key, new_identity_contract_nonce, settings.user_fee_increase.unwrap_or_default(), + token_payment_info, signer, sdk.version(), None, @@ -92,6 +97,7 @@ impl PurchaseDocument for Document { document_type: DocumentType, purchaser_id: Identifier, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result { @@ -102,6 +108,7 @@ impl PurchaseDocument for Document { document_type, purchaser_id, identity_public_key, + token_payment_info, signer, settings, ) diff --git a/packages/rs-sdk/src/platform/transition/transfer_document.rs b/packages/rs-sdk/src/platform/transition/transfer_document.rs index bd4a87e2dd6..f63115c0638 100644 --- a/packages/rs-sdk/src/platform/transition/transfer_document.rs +++ b/packages/rs-sdk/src/platform/transition/transfer_document.rs @@ -11,6 +11,7 @@ use dpp::identity::IdentityPublicKey; use dpp::state_transition::batch_transition::methods::v0::DocumentsBatchTransitionMethodsV0; use dpp::state_transition::batch_transition::BatchTransition; use dpp::state_transition::StateTransition; +use dpp::tokens::token_payment_info::TokenPaymentInfo; use rs_dapi_client::{DapiRequest, IntoInner}; #[async_trait::async_trait] @@ -24,6 +25,7 @@ pub trait TransferDocument: Waitable { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result; @@ -35,6 +37,7 @@ pub trait TransferDocument: Waitable { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result; @@ -48,6 +51,7 @@ impl TransferDocument for Document { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result { @@ -69,6 +73,7 @@ impl TransferDocument for Document { &identity_public_key, new_identity_contract_nonce, settings.user_fee_increase.unwrap_or_default(), + token_payment_info, signer, sdk.version(), None, @@ -95,6 +100,7 @@ impl TransferDocument for Document { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result { @@ -104,6 +110,7 @@ impl TransferDocument for Document { sdk, document_type, identity_public_key, + token_payment_info, signer, settings, ) diff --git a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs index b6e651d5eec..d441551783b 100644 --- a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs +++ b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs @@ -12,6 +12,7 @@ use dpp::identity::IdentityPublicKey; use dpp::state_transition::batch_transition::methods::v0::DocumentsBatchTransitionMethodsV0; use dpp::state_transition::batch_transition::BatchTransition; use dpp::state_transition::StateTransition; +use dpp::tokens::token_payment_info::TokenPaymentInfo; #[async_trait::async_trait] /// A trait for updating the price of a document on Platform @@ -24,6 +25,7 @@ pub trait UpdatePriceOfDocument: Waitable { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result; @@ -35,6 +37,7 @@ pub trait UpdatePriceOfDocument: Waitable { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result; @@ -48,6 +51,7 @@ impl UpdatePriceOfDocument for Document { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result { @@ -69,6 +73,7 @@ impl UpdatePriceOfDocument for Document { &identity_public_key, new_identity_contract_nonce, settings.user_fee_increase.unwrap_or_default(), + token_payment_info, signer, sdk.version(), None, @@ -87,11 +92,12 @@ impl UpdatePriceOfDocument for Document { sdk: &Sdk, document_type: DocumentType, identity_public_key: IdentityPublicKey, + token_payment_info: Option, signer: &S, settings: Option, ) -> Result { let state_transition = self - .update_price_of_document(price, sdk, document_type, identity_public_key, signer, None) + .update_price_of_document(price, sdk, document_type, identity_public_key, token_payment_info, signer, None) .await?; Self::wait_for_response(sdk, state_transition, settings).await diff --git a/packages/wasm-dpp/src/document/factory.rs b/packages/wasm-dpp/src/document/factory.rs index 24b1049505c..d849ebdeabb 100644 --- a/packages/wasm-dpp/src/document/factory.rs +++ b/packages/wasm-dpp/src/document/factory.rs @@ -25,6 +25,7 @@ use dpp::state_transition::batch_transition::batched_transition::document_transi use dpp::version::PlatformVersion; use std::convert::TryFrom; use std::str::FromStr; +use dpp::tokens::token_payment_info::TokenPaymentInfo; #[wasm_bindgen(js_name=DocumentTransitions)] #[derive(Debug, Default)] @@ -157,11 +158,11 @@ impl DocumentFactoryWASM { let documents: Vec<( DocumentTransitionActionType, - Vec<(Document, DocumentTypeRef, Bytes32)>, + Vec<(Document, DocumentTypeRef, Bytes32, Option)>, )> = documents_by_action .iter() .map(|(action_type, documents)| { - let documents_with_refs: Vec<(Document, DocumentTypeRef, Bytes32)> = documents + let documents_with_refs: Vec<(Document, DocumentTypeRef, Bytes32, Option)> = documents .iter() .map(|extended_document| { ( @@ -171,6 +172,7 @@ impl DocumentFactoryWASM { .document_type_for_name(extended_document.document_type_name()) .expect("should be able to get document type"), extended_document.entropy().to_owned(), + extended_document.token_payment_info(), ) }) .collect(); diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs index d7080c5da83..c324202d2b9 100644 --- a/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs @@ -24,6 +24,7 @@ use dpp::state_transition::batch_transition::document_replace_transition::v0::v0 use dpp::state_transition::batch_transition::batched_transition::document_purchase_transition::v0::v0_methods::DocumentPurchaseTransitionV0Methods; use dpp::state_transition::batch_transition::batched_transition::document_transfer_transition::v0::v0_methods::DocumentTransferTransitionV0Methods; use dpp::state_transition::batch_transition::batched_transition::document_update_price_transition::v0::v0_methods::DocumentUpdatePriceTransitionV0Methods; +use dpp::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; use crate::{ buffer::Buffer, identifier::{identifier_from_js_value, IdentifierWrapper}, @@ -89,9 +90,7 @@ impl DocumentTransitionWasm { #[wasm_bindgen(js_name=getIdentityContractNonce)] pub fn get_identity_contract_nonce(&self) -> JsValue { - match self.0.base() { - DocumentBaseTransition::V0(v0) => JsValue::from(v0.identity_contract_nonce), - } + JsValue::from(self.0.base().identity_contract_nonce()) } #[wasm_bindgen(js_name=getRevision)] diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 90a642897b0..738f1505d17 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError, }; use wasm_bindgen::{JsError, JsValue}; -use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, UnknownDocumentCreationRestrictionModeError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; +use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; @@ -84,7 +84,7 @@ use dpp::consensus::state::identity::no_transfer_key_for_core_withdrawal_availab use dpp::consensus::state::identity::RecipientIdentityDoesNotExistError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; -use dpp::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountNotFrozenError, IdentityTokenAccountFrozenError, TokenIsPausedError, IdentityTokenAccountAlreadyFrozenError, UnauthorizedTokenActionError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, TokenMintPastMaxSupplyError, NewTokensDestinationIdentityDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, InvalidGroupPositionError, TokenAlreadyPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, TokenTransferRecipientIdentityNotExistError, PreProgrammedDistributionTimestampInPastError}; +use dpp::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountNotFrozenError, IdentityTokenAccountFrozenError, TokenIsPausedError, IdentityTokenAccountAlreadyFrozenError, UnauthorizedTokenActionError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, TokenMintPastMaxSupplyError, NewTokensDestinationIdentityDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, InvalidGroupPositionError, TokenAlreadyPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, TokenTransferRecipientIdentityNotExistError, PreProgrammedDistributionTimestampInPastError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError}; use dpp::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; @@ -390,6 +390,12 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::PreProgrammedDistributionTimestampInPastError(e) => { generic_consensus_error!(PreProgrammedDistributionTimestampInPastError, e).into() } + StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError(e) => { + generic_consensus_error!(IdentityHasNotAgreedToPayRequiredTokenAmountError, e).into() + } + StateError::RequiredTokenPaymentInfoNotSetError(e) => { + generic_consensus_error!(RequiredTokenPaymentInfoNotSetError, e).into() + } } } @@ -743,6 +749,9 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::MissingDefaultLocalizationError(e) => { generic_consensus_error!(MissingDefaultLocalizationError, e).into() } + BasicError::UnknownGasFeesPaidByError(e) => { + generic_consensus_error!(UnknownGasFeesPaidByError, e).into() + } } } From 1c4f87182dbe3e4ed8d4d7537548f90a85678b56 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 28 Mar 2025 12:45:11 +0700 Subject: [PATCH 05/18] more --- .../document_type/accessors/mod.rs | 4 +- .../src/document/document_factory/v0/mod.rs | 2 + .../src/document/extended_document/mod.rs | 3 +- .../extended_document/serde_serialize.rs | 1 + .../src/document/extended_document/v0/mod.rs | 51 +- .../extended_document/v0/serialize.rs | 1 + .../extended_document/v1/json_conversion.rs | 54 -- .../src/document/extended_document/v1/mod.rs | 560 ------------------ .../v1/platform_value_conversion.rs | 77 --- .../extended_document/v1/serialize.rs | 213 ------- .../specialized_document_factory/v0/mod.rs | 2 + packages/rs-dpp/src/errors/consensus/codes.rs | 1 + .../src/errors/consensus/state/state_error.rs | 5 +- ...reed_to_pay_required_token_amount_error.rs | 10 +- ...ty_trying_to_pay_with_wrong_token_error.rs | 99 ++++ .../src/errors/consensus/state/token/mod.rs | 2 + ...quired_token_payment_info_not_set_error.rs | 10 +- .../tokens/token_payment_info/methods/mod.rs | 1 + .../token_payment_info/methods/v0/mod.rs | 31 + .../src/tokens/token_payment_info/mod.rs | 18 +- .../transformer.rs | 14 +- .../v0/transformer.rs | 107 +++- .../transformer.rs | 10 +- .../v0/transformer.rs | 30 +- .../transformer.rs | 10 +- .../v0/transformer.rs | 6 +- .../transformer.rs | 6 +- .../v0/transformer.rs | 4 +- .../transformer.rs | 6 +- .../v0/transformer.rs | 4 +- .../transformer.rs | 6 +- .../v0/transformer.rs | 4 +- .../transformer.rs | 6 +- .../v0/transformer.rs | 4 +- 34 files changed, 403 insertions(+), 959 deletions(-) delete mode 100644 packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs delete mode 100644 packages/rs-dpp/src/document/extended_document/v1/mod.rs delete mode 100644 packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs delete mode 100644 packages/rs-dpp/src/document/extended_document/v1/serialize.rs create mode 100644 packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs create mode 100644 packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs create mode 100644 packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs diff --git a/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs b/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs index a702f469345..652439075b6 100644 --- a/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs @@ -628,7 +628,7 @@ impl DocumentTypeV1Getters for DocumentType { } impl DocumentTypeV1Getters for DocumentTypeRef<'_> { - fn document_creation_token_cost(&self) -> Option<(DocumentActionTokenCost)> { + fn document_creation_token_cost(&self) -> Option { match self { DocumentTypeRef::V0(_) => None, DocumentTypeRef::V1(v1) => v1.document_creation_token_cost(), @@ -672,7 +672,7 @@ impl DocumentTypeV1Getters for DocumentTypeRef<'_> { } impl DocumentTypeV1Getters for DocumentTypeMutRef<'_> { - fn document_creation_token_cost(&self) -> Option<(DocumentActionTokenCost)> { + fn document_creation_token_cost(&self) -> Option { match self { DocumentTypeMutRef::V0(_) => None, DocumentTypeMutRef::V1(v1) => v1.document_creation_token_cost(), diff --git a/packages/rs-dpp/src/document/document_factory/v0/mod.rs b/packages/rs-dpp/src/document/document_factory/v0/mod.rs index 3862cecc068..7cfbfed6757 100644 --- a/packages/rs-dpp/src/document/document_factory/v0/mod.rs +++ b/packages/rs-dpp/src/document/document_factory/v0/mod.rs @@ -192,6 +192,7 @@ impl DocumentFactoryV0 { data_contract: data_contract.clone(), metadata: None, entropy: Bytes32::new(document_entropy), + token_payment_info: None, } .into()), version => Err(ProtocolError::UnknownVersionMismatch { @@ -323,6 +324,7 @@ impl DocumentFactoryV0 { data_contract: data_contract.clone(), metadata: None, entropy: Bytes32::default(), + token_payment_info: None, } .into()), version => Err(ProtocolError::UnknownVersionMismatch { diff --git a/packages/rs-dpp/src/document/extended_document/mod.rs b/packages/rs-dpp/src/document/extended_document/mod.rs index c48d2e07659..4d967024120 100644 --- a/packages/rs-dpp/src/document/extended_document/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/mod.rs @@ -4,7 +4,6 @@ mod fields; mod serde_serialize; mod serialize; pub(crate) mod v0; -pub(crate) mod v1; pub use fields::{property_names, IDENTIFIER_FIELDS}; @@ -33,7 +32,6 @@ use derive_more::From; #[derive(Debug, Clone, PlatformVersioned, From)] pub enum ExtendedDocument { V0(ExtendedDocumentV0), - V1(ExtendedDocumentV1), } impl ExtendedDocument { @@ -645,6 +643,7 @@ mod test { metadata: None, data_contract_id, entropy: Default::default(), + token_payment_info: None, } .into() } diff --git a/packages/rs-dpp/src/document/extended_document/serde_serialize.rs b/packages/rs-dpp/src/document/extended_document/serde_serialize.rs index 799e5d9deb4..00c6741ebe6 100644 --- a/packages/rs-dpp/src/document/extended_document/serde_serialize.rs +++ b/packages/rs-dpp/src/document/extended_document/serde_serialize.rs @@ -81,6 +81,7 @@ impl<'de> Visitor<'de> for ExtendedDocumentVisitor { data_contract, metadata: None, entropy: Bytes32::default(), + token_payment_info: None, })), _ => Err(serde::de::Error::unknown_variant( &format!("{}", version), diff --git a/packages/rs-dpp/src/document/extended_document/v0/mod.rs b/packages/rs-dpp/src/document/extended_document/v0/mod.rs index 226502b2172..df61308a6bf 100644 --- a/packages/rs-dpp/src/document/extended_document/v0/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/v0/mod.rs @@ -11,7 +11,7 @@ use crate::data_contract::DataContract; feature = "document-json-conversion" ))] use crate::document::extended_document::fields::property_names; -use crate::document::{Document, DocumentV0Getters, ExtendedDocument}; +use crate::document::{Document, DocumentV0Getters}; use crate::identity::TimestampMillis; use crate::metadata::Metadata; use crate::prelude::{BlockHeight, CoreBlockHeight, Revision}; @@ -47,6 +47,7 @@ use platform_value::converter::serde_json::BTreeValueJsonConverter; use platform_version::version::PlatformVersion; #[cfg(feature = "document-json-conversion")] use serde_json::Value as JsonValue; +use crate::tokens::token_payment_info::TokenPaymentInfo; /// The `ExtendedDocumentV0` struct represents the data provided by the platform in response to a query. #[derive(Debug, Clone)] @@ -119,6 +120,15 @@ pub struct ExtendedDocumentV0 { serde(rename = "$entropy") )] pub entropy: Bytes32, + /// A field representing the token payment info. + #[cfg_attr( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + serde(rename = "$tokenPaymentInfo") + )] + pub token_payment_info: Option, } impl ExtendedDocumentV0 { @@ -218,6 +228,7 @@ impl ExtendedDocumentV0 { document: Document, data_contract: DataContract, document_type_name: String, + token_payment_info: Option, ) -> Self { Self { document_type_name, @@ -226,6 +237,7 @@ impl ExtendedDocumentV0 { data_contract, metadata: None, entropy: Default::default(), + token_payment_info, } } @@ -291,6 +303,14 @@ impl ExtendedDocumentV0 { .clone() .into_btree_string_map() .map_err(ProtocolError::ValueError)?; + + let token_payment_info = properties + .remove_optional_map_as_btree_map_keep_values_as_platform_value( + property_names::TOKEN_PAYMENT_INFO, + ) + .ok() + .flatten().map(|map| map.try_into()).transpose()?; + let document_type_name = properties .remove_string(property_names::DOCUMENT_TYPE_NAME) .map_err(ProtocolError::ValueError)?; @@ -305,6 +325,7 @@ impl ExtendedDocumentV0 { data_contract_id, metadata: None, entropy: Default::default(), + token_payment_info, }; extended_document.data_contract_id = Identifier::new( @@ -340,6 +361,13 @@ impl ExtendedDocumentV0 { .remove_string(property_names::DOCUMENT_TYPE_NAME) .map_err(ProtocolError::ValueError)?; + let token_payment_info = properties + .remove_optional_map_as_btree_map_keep_values_as_platform_value( + property_names::TOKEN_PAYMENT_INFO, + ) + .ok() + .flatten().map(|map| map.try_into()).transpose()?; + let document_type = data_contract.document_type_for_name(document_type_name.as_str())?; let identifiers = document_type.identifier_paths().to_owned(); @@ -364,6 +392,7 @@ impl ExtendedDocumentV0 { data_contract_id, metadata: None, entropy: Default::default(), + token_payment_info, }; extended_document.data_contract_id = properties @@ -396,6 +425,13 @@ impl ExtendedDocumentV0 { property_names::DATA_CONTRACT_ID.to_string(), JsonValue::String(bs58::encode(self.data_contract_id.to_buffer()).into_string()), ); + if let Some(token_payment_info) = self.token_payment_info { + let value : Value = token_payment_info.try_into()?; + value_mut.insert( + property_names::TOKEN_PAYMENT_INFO.to_string(), + value.try_into_validating_json()?, + ); + } Ok(value) } @@ -410,6 +446,12 @@ impl ExtendedDocumentV0 { property_names::DATA_CONTRACT_ID.to_string(), Value::Identifier(self.data_contract_id.to_buffer()), ); + if let Some(token_payment_info) = self.token_payment_info { + object.insert( + property_names::TOKEN_PAYMENT_INFO.to_string(), + token_payment_info.try_into()?, + ); + } Ok(object) } @@ -419,6 +461,7 @@ impl ExtendedDocumentV0 { document_type_name, data_contract_id, document, + token_payment_info, .. } = self; @@ -432,6 +475,12 @@ impl ExtendedDocumentV0 { property_names::DATA_CONTRACT_ID.to_string(), Value::Identifier(data_contract_id.to_buffer()), ); + if let Some(token_payment_info) = token_payment_info { + object.insert( + property_names::TOKEN_PAYMENT_INFO.to_string(), + token_payment_info.try_into()?, + ); + } Ok(object) } diff --git a/packages/rs-dpp/src/document/extended_document/v0/serialize.rs b/packages/rs-dpp/src/document/extended_document/v0/serialize.rs index 255d49bd960..0cecc57ba5a 100644 --- a/packages/rs-dpp/src/document/extended_document/v0/serialize.rs +++ b/packages/rs-dpp/src/document/extended_document/v0/serialize.rs @@ -125,6 +125,7 @@ impl ExtendedDocumentPlatformDeserializationMethodsV0 for ExtendedDocumentV0 { metadata: None, entropy: Default::default(), + token_payment_info: None, }) } } diff --git a/packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs b/packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs deleted file mode 100644 index cbc8cb4a266..00000000000 --- a/packages/rs-dpp/src/document/extended_document/v1/json_conversion.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::data_contract::conversion::json::DataContractJsonConversionMethodsV0; -use crate::document::extended_document::fields::property_names; -use crate::document::extended_document::v0::ExtendedDocumentV0; -use crate::document::serialization_traits::{ - DocumentJsonMethodsV0, DocumentPlatformValueMethodsV0, -}; - -use crate::ProtocolError; -use platform_value::Identifier; -use platform_version::version::PlatformVersion; -use serde::Deserialize; -use serde_json::Value as JsonValue; -use std::convert::TryInto; - -impl DocumentJsonMethodsV0<'_> for ExtendedDocumentV0 { - fn to_json_with_identifiers_using_bytes( - &self, - platform_version: &PlatformVersion, - ) -> Result { - let mut json = self - .document - .to_json_with_identifiers_using_bytes(platform_version)?; - let value_mut = json.as_object_mut().unwrap(); - let contract = self.data_contract.to_validating_json(platform_version)?; - value_mut.insert(property_names::DATA_CONTRACT.to_owned(), contract); - value_mut.insert( - property_names::DOCUMENT_TYPE_NAME.to_owned(), - self.document_type_name.clone().into(), - ); - Ok(json) - } - - fn to_json(&self, platform_version: &PlatformVersion) -> Result { - let mut json = self.document.to_json(platform_version)?; - let value_mut = json.as_object_mut().unwrap(); - let contract = self.data_contract.to_json(platform_version)?; - value_mut.insert(property_names::DATA_CONTRACT.to_owned(), contract); - value_mut.insert( - property_names::DOCUMENT_TYPE_NAME.to_owned(), - self.document_type_name.clone().into(), - ); - Ok(json) - } - - fn from_json_value( - document_value: JsonValue, - platform_version: &PlatformVersion, - ) -> Result - where - for<'de> S: Deserialize<'de> + TryInto, - { - Self::from_platform_value(document_value.into(), platform_version) - } -} diff --git a/packages/rs-dpp/src/document/extended_document/v1/mod.rs b/packages/rs-dpp/src/document/extended_document/v1/mod.rs deleted file mode 100644 index 65b269897b8..00000000000 --- a/packages/rs-dpp/src/document/extended_document/v1/mod.rs +++ /dev/null @@ -1,560 +0,0 @@ -#[cfg(feature = "document-json-conversion")] -mod json_conversion; -#[cfg(feature = "document-value-conversion")] -mod platform_value_conversion; -mod serialize; - -use crate::data_contract::document_type::DocumentTypeRef; -use crate::data_contract::DataContract; -#[cfg(any( - feature = "document-value-conversion", - feature = "document-json-conversion" -))] -use crate::document::extended_document::fields::property_names; -use crate::document::{Document, DocumentV0Getters, ExtendedDocument}; -use crate::identity::TimestampMillis; -use crate::metadata::Metadata; -use crate::prelude::{BlockHeight, CoreBlockHeight, Revision}; - -use crate::util::hash::hash_double_to_vec; -use crate::ProtocolError; - -use platform_value::btreemap_extensions::{ - BTreeValueMapInsertionPathHelper, BTreeValueMapPathHelper, -}; -#[cfg(feature = "document-value-conversion")] -use platform_value::btreemap_extensions::{ - BTreeValueMapReplacementPathHelper, BTreeValueRemoveFromMapHelper, -}; -use platform_value::{Bytes32, Identifier, ReplacementType, Value}; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; - -use crate::data_contract::accessors::v0::DataContractV0Getters; -use crate::data_contract::document_type::accessors::DocumentTypeV0Getters; -use crate::data_contract::document_type::methods::DocumentTypeBasicMethods; -#[cfg(feature = "validation")] -use crate::data_contract::validate_document::DataContractDocumentValidationMethodsV0; -#[cfg(feature = "document-json-conversion")] -use crate::document::serialization_traits::DocumentJsonMethodsV0; -#[cfg(feature = "document-value-conversion")] -use crate::document::serialization_traits::DocumentPlatformValueMethodsV0; -use crate::document::serialization_traits::ExtendedDocumentPlatformConversionMethodsV0; -#[cfg(feature = "validation")] -use crate::validation::SimpleConsensusValidationResult; -#[cfg(feature = "document-json-conversion")] -use platform_value::converter::serde_json::BTreeValueJsonConverter; -use platform_version::version::PlatformVersion; -#[cfg(feature = "document-json-conversion")] -use serde_json::Value as JsonValue; -use crate::tokens::token_payment_info::TokenPaymentInfo; - -/// The `ExtendedDocumentV0` struct represents the data provided by the platform in response to a query. -#[derive(Debug, Clone)] -#[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - derive(Serialize, Deserialize) -)] -pub struct ExtendedDocumentV1 { - /// The document type name, stored as a string. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(rename = "$type") - )] - pub document_type_name: String, - - /// The identifier of the associated data contract. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(rename = "$dataContractId") - )] - pub data_contract_id: Identifier, - - /// The actual document object containing the data. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(flatten) - )] - pub document: Document, - - // TODO: We should remove it from here, or at least keep a ref - // also there is no point to keep both contract and its ID - /// The data contract associated with the document. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(rename = "$dataContract") - )] - pub data_contract: DataContract, - - /// An optional field for metadata associated with the document. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(rename = "$metadata", default) - )] - pub metadata: Option, - - /// A field representing the entropy, stored as `Bytes32`. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(rename = "$entropy") - )] - pub entropy: Bytes32, - /// A field representing the token payment info. - #[cfg_attr( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - serde(rename = "$tokenPaymentInfo") - )] - pub token_payment_info: Option, -} - -impl ExtendedDocumentV1 { - #[cfg(feature = "document-json-conversion")] - pub(super) fn properties_as_json_data(&self) -> Result { - self.document - .properties() - .to_json_value() - .map_err(ProtocolError::ValueError) - } - - pub fn get_optional_value(&self, key: &str) -> Option<&Value> { - self.document.properties().get(key) - } - - pub fn properties(&self) -> &BTreeMap { - self.document.properties() - } - - pub fn properties_as_mut(&mut self) -> &mut BTreeMap { - self.document.properties_mut() - } - - pub fn id(&self) -> Identifier { - self.document.id() - } - - pub fn owner_id(&self) -> Identifier { - self.document.owner_id() - } - - pub fn document_type(&self) -> Result { - // We can unwrap because the Document can not be created without a valid Document Type - self.data_contract - .document_type_for_name(self.document_type_name.as_str()) - .map_err(ProtocolError::DataContractError) - } - - pub fn can_be_modified(&self) -> Result { - self.document_type() - .map(|document_type| document_type.documents_mutable()) - } - - pub fn requires_revision(&self) -> Result { - self.document_type() - .map(|document_type| document_type.requires_revision()) - } - - pub fn revision(&self) -> Option { - self.document.revision() - } - - /// Returns an optional block timestamp at which the document was created. - /// It will be None if it is not required by the schema. - pub fn created_at(&self) -> Option { - self.document.created_at() - } - - /// Returns an optional block timestamp at which the document was updated. - /// It will be None if it is not required by the schema. - pub fn updated_at(&self) -> Option { - self.document.updated_at() - } - - /// Returns an optional block height at which the document was created. - /// It will be None if it is not required by the schema. - pub fn created_at_block_height(&self) -> Option { - self.document.created_at_block_height() - } - - /// Returns an optional block height at which the document was last updated. - /// It will be None if it is not required by the schema. - pub fn updated_at_block_height(&self) -> Option { - self.document.updated_at_block_height() - } - - /// Returns an optional core block height at which the document was created. - /// It will be None if it is not required by the schema. - pub fn created_at_core_block_height(&self) -> Option { - self.document.created_at_core_block_height() - } - - /// Returns an optional core block height at which the document was last updated. - /// It will be None if it is not required by the schema. - pub fn updated_at_core_block_height(&self) -> Option { - self.document.updated_at_core_block_height() - } - - /// Create an extended document with additional information. - /// - /// # Arguments - /// - /// * `document` - A `Document` instance. - /// * `data_contract` - A `DataContract` instance. - /// * `document_type_name` - A `String` representing the document type name. - pub fn from_document_with_additional_info( - document: Document, - data_contract: DataContract, - document_type_name: String, - token_payment_info: Option - ) -> Self { - Self { - document_type_name, - data_contract_id: data_contract.id(), - document, - data_contract, - metadata: None, - entropy: Default::default(), - token_payment_info, - } - } - - #[cfg(feature = "document-json-conversion")] - /// Create an extended document from a JSON string. - /// - /// # Arguments - /// - /// * `string` - A JSON string representing the extended document. - /// * `contract` - A `DataContract` instance. - /// - /// # Errors - /// - /// Returns a `ProtocolError` if there is an error decoding the JSON string. - pub fn from_json_string( - string: &str, - contract: DataContract, - platform_version: &PlatformVersion, - ) -> Result { - let json_value: JsonValue = serde_json::from_str(string).map_err(|_| { - ProtocolError::StringDecodeError("error decoding from json string".to_string()) - })?; - Self::from_untrusted_platform_value(json_value.into(), contract, platform_version) - } - - #[cfg(feature = "document-json-conversion")] - /// Create an extended document from a raw JSON document. - /// - /// # Arguments - /// - /// * `raw_document` - A `JsonValue` representing the raw document. - /// * `data_contract` - A `DataContract` instance. - /// - /// # Errors - /// - /// Returns a `ProtocolError` if there is an error processing the raw JSON document. - pub fn from_raw_json_document( - raw_document: JsonValue, - data_contract: DataContract, - platform_version: &PlatformVersion, - ) -> Result { - Self::from_untrusted_platform_value(raw_document.into(), data_contract, platform_version) - } - - #[cfg(feature = "document-value-conversion")] - /// Create an extended document from a trusted platform value object where fields are already in - /// the proper format for the contract. - /// - /// # Arguments - /// - /// * `document_value` - A `Value` representing the document value. - /// * `data_contract` - A `DataContract` instance. - /// - /// # Errors - /// - /// Returns a `ProtocolError` if there is an error processing the trusted platform value. - pub fn from_trusted_platform_value( - document_value: Value, - data_contract: DataContract, - platform_version: &PlatformVersion, - ) -> Result { - let mut properties = document_value - .clone() - .into_btree_string_map() - .map_err(ProtocolError::ValueError)?; - let document_type_name = properties - .remove_string(property_names::DOCUMENT_TYPE_NAME) - .map_err(ProtocolError::ValueError)?; - - let token_payment_info = properties - .remove_optional_map_as_btree_map_keep_values_as_platform_value( - property_names::TOKEN_PAYMENT_INFO, - ) - .ok() - .flatten().map(|map| map.try_into()).transpose()?; - - let document = Document::from_platform_value(document_value, platform_version)?; - - - let data_contract_id = data_contract.id(); - let mut extended_document = Self { - data_contract, - document_type_name, - document, - data_contract_id, - metadata: None, - entropy: Default::default(), - token_payment_info, - }; - - extended_document.data_contract_id = Identifier::new( - properties - .remove_optional_hash256_bytes(property_names::DATA_CONTRACT_ID)? - .unwrap_or(extended_document.data_contract.id().to_buffer()), - ); - Ok(extended_document) - } - - #[cfg(feature = "document-value-conversion")] - /// Create an extended document from an untrusted platform value object where fields might not - /// be in the proper format for the contract. - /// - /// # Arguments - /// - /// * `document_value` - A `Value` representing the document value. - /// * `data_contract` - A `DataContract` instance. - /// - /// # Errors - /// - /// Returns a `ProtocolError` if there is an error processing the untrusted platform value. - pub fn from_untrusted_platform_value( - mut document_value: Value, - data_contract: DataContract, - platform_version: &PlatformVersion, - ) -> Result { - let mut properties = document_value - .clone() - .into_btree_string_map() - .map_err(ProtocolError::ValueError)?; - let document_type_name = properties - .remove_string(property_names::DOCUMENT_TYPE_NAME) - .map_err(ProtocolError::ValueError)?; - - let token_payment_info = properties - .remove_optional_map_as_btree_map_keep_values_as_platform_value( - property_names::TOKEN_PAYMENT_INFO, - ) - .ok() - .flatten().map(|map| map.try_into()).transpose()?; - - let document_type = data_contract.document_type_for_name(document_type_name.as_str())?; - - let identifiers = document_type.identifier_paths().to_owned(); - let binary_paths = document_type.binary_paths(); - - document_value.replace_at_paths(["$id", "$ownerId"], ReplacementType::Identifier)?; - document_value.replace_at_paths( - identifiers.iter().map(|s| s.as_str()), - ReplacementType::Identifier, - )?; - document_value.replace_at_paths( - binary_paths.iter().map(|s| s.as_str()), - ReplacementType::BinaryBytes, - )?; - - let document = Document::from_platform_value(document_value, platform_version)?; - let data_contract_id = data_contract.id(); - let mut extended_document = Self { - data_contract, - document_type_name, - document, - data_contract_id, - metadata: None, - entropy: Default::default(), - token_payment_info, - }; - - extended_document.data_contract_id = properties - .remove_optional_identifier(property_names::DATA_CONTRACT_ID)? - .unwrap_or(extended_document.data_contract.id()); - extended_document - .document - .properties_mut() - .replace_at_paths(&identifiers, ReplacementType::Identifier)?; - Ok(extended_document) - } - - #[cfg(feature = "document-json-conversion")] - /// Convert the extended document to a pretty JSON object. - /// - /// # Errors - /// - /// Returns a `ProtocolError` if there is an error converting the document to pretty JSON. - pub fn to_pretty_json( - &self, - platform_version: &PlatformVersion, - ) -> Result { - let mut value = self.document.to_json(platform_version)?; - let value_mut = value.as_object_mut().unwrap(); - value_mut.insert( - property_names::DOCUMENT_TYPE_NAME.to_string(), - JsonValue::String(self.document_type_name.clone()), - ); - value_mut.insert( - property_names::DATA_CONTRACT_ID.to_string(), - JsonValue::String(bs58::encode(self.data_contract_id.to_buffer()).into_string()), - ); - if let Some(token_payment_info) = self.token_payment_info { - value_mut.insert( - property_names::TOKEN_PAYMENT_INFO.to_string(), - token_payment_info.into(), - ); - } - Ok(value) - } - - #[cfg(feature = "document-value-conversion")] - pub fn to_map_value(&self) -> Result, ProtocolError> { - let mut object = self.document.to_map_value()?; - object.insert( - property_names::DOCUMENT_TYPE_NAME.to_string(), - Value::Text(self.document_type_name.clone()), - ); - object.insert( - property_names::DATA_CONTRACT_ID.to_string(), - Value::Identifier(self.data_contract_id.to_buffer()), - ); - if let Some(token_payment_info) = self.token_payment_info { - object.insert( - property_names::TOKEN_PAYMENT_INFO.to_string(), - token_payment_info.into(), - ); - } - Ok(object) - } - - #[cfg(feature = "document-value-conversion")] - pub fn into_map_value(self) -> Result, ProtocolError> { - let ExtendedDocumentV1 { - document_type_name, - data_contract_id, - document, - token_payment_info, - .. - } = self; - - let mut object = document.into_map_value()?; - object.insert(property_names::FEATURE_VERSION.to_string(), Value::U16(0)); - object.insert( - property_names::DOCUMENT_TYPE_NAME.to_string(), - Value::Text(document_type_name), - ); - object.insert( - property_names::DATA_CONTRACT_ID.to_string(), - Value::Identifier(data_contract_id.to_buffer()), - ); - if let Some(token_payment_info) = token_payment_info { - object.insert( - property_names::TOKEN_PAYMENT_INFO.to_string(), - token_payment_info.into(), - ); - } - Ok(object) - } - - #[cfg(feature = "document-value-conversion")] - pub fn into_value(self) -> Result { - Ok(self.into_map_value()?.into()) - } - - #[cfg(feature = "document-value-conversion")] - pub fn to_value(&self) -> Result { - Ok(self.to_map_value()?.into()) - } - - #[cfg(feature = "document-json-conversion")] - pub fn to_json_object_for_validation(&self) -> Result { - self.to_value()? - .try_into_validating_json() - .map_err(ProtocolError::ValueError) - } - - pub fn hash(&self, platform_version: &PlatformVersion) -> Result, ProtocolError> { - Ok(hash_double_to_vec( - ExtendedDocumentPlatformConversionMethodsV0::serialize_to_bytes( - self, - platform_version, - )?, - )) - } - - /// Set the value under given path. - /// The path supports syntax from `lodash` JS lib. Example: "root.people[0].name". - /// If parents are not present they will be automatically created - pub fn set(&mut self, path: &str, value: Value) -> Result<(), ProtocolError> { - Ok(self.document.properties_mut().insert_at_path(path, value)?) - } - - /// Set the value under given path. - /// The path supports syntax from `lodash` JS lib. Example: "root.people[0].name". - /// If parents are not present they will be automatically created - pub fn set_untrusted(&mut self, path: &str, value: Value) -> Result<(), ProtocolError> { - let document_type = self.document_type()?; - - let identifiers = document_type.identifier_paths(); - let binary_paths = document_type.binary_paths(); - - if identifiers.contains(path) { - let value = - ReplacementType::Identifier.replace_for_bytes(value.to_identifier_bytes()?)?; - self.set(path, value) - } else if binary_paths.contains(path) { - let value = - ReplacementType::BinaryBytes.replace_for_bytes(value.to_identifier_bytes()?)?; - self.set(path, value) - } else { - self.set(path, value) - } - } - - /// Retrieves field specified by path - pub fn get(&self, path: &str) -> Option<&Value> { - self.properties().get_optional_at_path(path).ok().flatten() - } - - // TODO: We probably should validate extended document on creation and during modification - // instead of have a dedicated method. That would be more Rust way approach - #[cfg(feature = "validation")] - /// Validate external document - pub fn validate( - &self, - platform_version: &PlatformVersion, - ) -> Result { - self.data_contract.validate_document( - &self.document_type_name, - &self.document, - platform_version, - ) - } -} diff --git a/packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs b/packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs deleted file mode 100644 index a27f8f7ea45..00000000000 --- a/packages/rs-dpp/src/document/extended_document/v1/platform_value_conversion.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::document::extended_document::v0::ExtendedDocumentV0; -use crate::document::property_names; -use crate::document::serialization_traits::DocumentPlatformValueMethodsV0; -use crate::version::PlatformVersion; -use crate::ProtocolError; - -use platform_value::Value; -use std::collections::BTreeMap; - -impl DocumentPlatformValueMethodsV0<'_> for ExtendedDocumentV0 { - fn to_map_value(&self) -> Result, ProtocolError> { - let mut map: BTreeMap = BTreeMap::new(); - map.insert(property_names::ID.to_string(), self.id().into()); - map.insert(property_names::OWNER_ID.to_string(), self.owner_id().into()); - - if let Some(created_at) = self.created_at() { - map.insert( - property_names::CREATED_AT.to_string(), - Value::U64(created_at), - ); - } - if let Some(updated_at) = self.updated_at() { - map.insert( - property_names::UPDATED_AT.to_string(), - Value::U64(updated_at), - ); - } - if let Some(revision) = self.revision() { - map.insert(property_names::REVISION.to_string(), Value::U64(revision)); - } - - map.extend(self.properties().clone()); - - Ok(map) - } - - fn into_map_value(self) -> Result, ProtocolError> { - let mut map: BTreeMap = BTreeMap::new(); - map.insert(property_names::ID.to_string(), self.id().into()); - map.insert(property_names::OWNER_ID.to_string(), self.owner_id().into()); - - if let Some(created_at) = self.created_at() { - map.insert( - property_names::CREATED_AT.to_string(), - Value::U64(created_at), - ); - } - if let Some(updated_at) = self.updated_at() { - map.insert( - property_names::UPDATED_AT.to_string(), - Value::U64(updated_at), - ); - } - if let Some(revision) = self.revision() { - map.insert(property_names::REVISION.to_string(), Value::U64(revision)); - } - - map.extend(self.properties().to_owned()); - - Ok(map) - } - - fn into_value(self) -> Result { - Ok(self.into_map_value()?.into()) - } - - fn to_object(&self) -> Result { - Ok(self.to_map_value()?.into()) - } - - fn from_platform_value( - document_value: Value, - _platform_version: &PlatformVersion, - ) -> Result { - Ok(platform_value::from_value(document_value)?) - } -} diff --git a/packages/rs-dpp/src/document/extended_document/v1/serialize.rs b/packages/rs-dpp/src/document/extended_document/v1/serialize.rs deleted file mode 100644 index 255d49bd960..00000000000 --- a/packages/rs-dpp/src/document/extended_document/v1/serialize.rs +++ /dev/null @@ -1,213 +0,0 @@ -use crate::document::Document; - -use crate::prelude::DataContract; - -use crate::ProtocolError; - -use crate::data_contract::accessors::v0::DataContractV0Getters; - -use crate::document::extended_document::v0::ExtendedDocumentV0; -use crate::document::serialization_traits::deserialize::v0::ExtendedDocumentPlatformDeserializationMethodsV0; -use crate::document::serialization_traits::serialize::v0::ExtendedDocumentPlatformSerializationMethodsV0; -use crate::document::serialization_traits::{ - DocumentPlatformConversionMethodsV0, ExtendedDocumentPlatformConversionMethodsV0, -}; - -use crate::serialization::{ - PlatformDeserializableWithBytesLenFromVersionedStructure, - PlatformSerializableWithPlatformVersion, -}; -use crate::version::PlatformVersion; - -use integer_encoding::{VarInt, VarIntReader}; - -use crate::consensus::basic::decode::DecodingError; -use crate::data_contract::errors::DataContractError; -use platform_version::version::FeatureVersion; - -impl ExtendedDocumentPlatformSerializationMethodsV0 for ExtendedDocumentV0 { - /// Serializes the extended document. - /// - /// The serialization of an extended document follows the pattern: - /// data contract | document type name | document - fn serialize_v0(&self, platform_version: &PlatformVersion) -> Result, ProtocolError> { - let mut buffer: Vec = 0.encode_var_vec(); //version 0 - - buffer.append( - &mut self - .data_contract - .serialize_to_bytes_with_platform_version(platform_version)?, - ); - buffer.push(self.document_type_name.len() as u8); - buffer.extend(self.document_type_name.as_bytes()); - buffer.append( - &mut self - .document - .serialize(self.document_type()?, platform_version)?, - ); - Ok(buffer) - } - - /// Serializes the extended document. - /// - /// The serialization of an extended document follows the pattern: - /// data contract | document type name | document - fn serialize_consume_v0( - self, - platform_version: &PlatformVersion, - ) -> Result, ProtocolError> { - let ExtendedDocumentV0 { - document_type_name, - document, - data_contract, - .. - } = self; - - let mut serialized_document = document.serialize_consume( - data_contract.document_type_for_name(document_type_name.as_str())?, - platform_version, - )?; - - let mut buffer: Vec = 0.encode_var_vec(); //version 0 - - buffer.append( - &mut data_contract - .serialize_consume_to_bytes_with_platform_version(platform_version)?, - ); - buffer.push(document_type_name.len() as u8); - buffer.append(&mut document_type_name.into_bytes()); - buffer.append(&mut serialized_document); - Ok(buffer) - } -} - -impl ExtendedDocumentPlatformDeserializationMethodsV0 for ExtendedDocumentV0 { - /// Reads a serialized document and creates a Document from it. - fn from_bytes_v0( - serialized_extended_document: &[u8], - platform_version: &PlatformVersion, - ) -> Result { - // first we deserialize the contract - let (data_contract, offset) = DataContract::versioned_deserialize_with_bytes_len( - serialized_extended_document, - true, //since this would only happen on the client, we should validate - platform_version, - )?; - let serialized_document = serialized_extended_document.split_at(offset).1; - let (document_type_name_len, rest) = - serialized_document - .split_first() - .ok_or(DataContractError::DecodingDocumentError( - DecodingError::new( - "error reading document type name len from serialized extended document" - .to_string(), - ), - ))?; - if serialized_document.len() < *document_type_name_len as usize { - return Err(ProtocolError::DecodingError( - "serialized extended document isn't big enough for the document type len" - .to_string(), - )); - } - let (document_type_name_bytes, rest) = rest.split_at(*document_type_name_len as usize); - let document_type_name = String::from_utf8(document_type_name_bytes.into()) - .map_err(|e| ProtocolError::DecodingError(e.to_string()))?; - - let document_type = data_contract.document_type_for_name(document_type_name.as_str())?; - - let document = Document::from_bytes(rest, document_type, platform_version)?; - - Ok(ExtendedDocumentV0 { - document_type_name, - data_contract_id: data_contract.id(), - document, - data_contract, - metadata: None, - - entropy: Default::default(), - }) - } -} - -impl ExtendedDocumentPlatformConversionMethodsV0 for ExtendedDocumentV0 { - /// Serializes the document. - /// - /// The serialization of a document follows the pattern: - /// id 32 bytes + owner_id 32 bytes + encoded values byte arrays - fn serialize_to_bytes( - &self, - platform_version: &PlatformVersion, - ) -> Result, ProtocolError> { - match platform_version - .dpp - .document_versions - .document_serialization_version - .default_current_version - { - 0 => self.serialize_v0(platform_version), - version => Err(ProtocolError::UnknownVersionMismatch { - method: "ExtendedDocumentV0::serialize".to_string(), - known_versions: vec![0], - received: version, - }), - } - } - - fn serialize_specific_version_to_bytes( - &self, - feature_version: FeatureVersion, - platform_version: &PlatformVersion, - ) -> Result, ProtocolError> { - match feature_version { - 0 => self.serialize_v0(platform_version), - version => Err(ProtocolError::UnknownVersionMismatch { - method: "ExtendedDocumentV0::serialize".to_string(), - known_versions: vec![0], - received: version, - }), - } - } - - /// Serializes and consumes the document. - /// - /// The serialization of a document follows the pattern: - /// id 32 bytes + owner_id 32 bytes + encoded values byte arrays - fn serialize_consume_to_bytes( - self, - platform_version: &PlatformVersion, - ) -> Result, ProtocolError> { - match platform_version - .dpp - .contract_versions - .contract_serialization_version - .default_current_version - { - 0 => self.serialize_consume_v0(platform_version), - version => Err(ProtocolError::UnknownVersionMismatch { - method: "DocumentV0::serialize_consume".to_string(), - known_versions: vec![0], - received: version, - }), - } - } - - /// Reads a serialized document and creates an ExtendedDocumentV0 from it. - fn from_bytes( - mut serialized_document: &[u8], - platform_version: &PlatformVersion, - ) -> Result { - let serialized_version = serialized_document.read_varint().map_err(|_| { - ProtocolError::DecodingError( - "error reading revision from serialized document for revision".to_string(), - ) - })?; - match serialized_version { - 0 => ExtendedDocumentV0::from_bytes_v0(serialized_document, platform_version), - version => Err(ProtocolError::UnknownVersionMismatch { - method: "ExtendedDocument::from_bytes (deserialization)".to_string(), - known_versions: vec![0], - received: version, - }), - } - } -} diff --git a/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs b/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs index 5f6605abb13..6e6ace91043 100644 --- a/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs +++ b/packages/rs-dpp/src/document/specialized_document_factory/v0/mod.rs @@ -200,6 +200,7 @@ impl SpecializedDocumentFactoryV0 { data_contract: self.data_contract.clone(), metadata: None, entropy: Bytes32::new(document_entropy), + token_payment_info: None, } .into()), version => Err(ProtocolError::UnknownVersionMismatch { @@ -332,6 +333,7 @@ impl SpecializedDocumentFactoryV0 { data_contract: self.data_contract.clone(), metadata: None, entropy: Bytes32::default(), + token_payment_info: None, } .into()), version => Err(ProtocolError::UnknownVersionMismatch { diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 1e6ac040db5..016509ac8e5 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -248,6 +248,7 @@ impl ErrorWithCode for StateError { Self::DocumentContestNotPaidForError(_) => 40114, Self::RequiredTokenPaymentInfoNotSetError(_) => 40115, Self::IdentityHasNotAgreedToPayRequiredTokenAmountError(_) => 40116, + Self::IdentityTryingToPayWithWrongTokenError(_) => 40117, // Identity Errors: 40200-40299 Self::IdentityAlreadyExistsError(_) => 40200, diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index fc16dd10175..c98088e2539 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -41,7 +41,7 @@ use crate::consensus::state::identity::missing_transfer_key_error::MissingTransf use crate::consensus::state::identity::no_transfer_key_for_core_withdrawal_available_error::NoTransferKeyForCoreWithdrawalAvailableError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; -use crate::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError, IdentityTokenAccountNotFrozenError, InvalidGroupPositionError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, NewTokensDestinationIdentityDoesNotExistError, TokenMintPastMaxSupplyError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, UnauthorizedTokenActionError, IdentityTokenAccountAlreadyFrozenError, TokenAlreadyPausedError, TokenIsPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, PreProgrammedDistributionTimestampInPastError, TokenTransferRecipientIdentityNotExistError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError}; +use crate::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError, IdentityTokenAccountNotFrozenError, InvalidGroupPositionError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, NewTokensDestinationIdentityDoesNotExistError, TokenMintPastMaxSupplyError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, UnauthorizedTokenActionError, IdentityTokenAccountAlreadyFrozenError, TokenAlreadyPausedError, TokenIsPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, PreProgrammedDistributionTimestampInPastError, TokenTransferRecipientIdentityNotExistError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError, IdentityTryingToPayWithWrongTokenError}; use crate::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; use crate::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use crate::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; @@ -284,6 +284,9 @@ pub enum StateError { #[error(transparent)] RequiredTokenPaymentInfoNotSetError(RequiredTokenPaymentInfoNotSetError), + + #[error(transparent)] + IdentityTryingToPayWithWrongTokenError(IdentityTryingToPayWithWrongTokenError), } impl From for ConsensusError { diff --git a/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs index c96784df1ce..28a5c7128ab 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs @@ -11,8 +11,7 @@ use thiserror::Error; Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] #[error( - "Identity {} has not agreed to pay the required token amount for token {}: required {}, min offer {:?}, max offer {:?}, action: {}", - identity_id, + "Identity has not agreed to pay the required token amount for token {}: required {}, min offer {:?}, max offer {:?}, action: {}", token_id, required_amount, identity_min_offer, @@ -22,7 +21,6 @@ use thiserror::Error; #[platform_serialize(unversioned)] pub struct IdentityHasNotAgreedToPayRequiredTokenAmountError { token_id: Identifier, - identity_id: Identifier, required_amount: u64, identity_min_offer: Option, identity_max_offer: Option, @@ -33,7 +31,6 @@ impl IdentityHasNotAgreedToPayRequiredTokenAmountError { #[allow(clippy::too_many_arguments)] pub fn new( token_id: Identifier, - identity_id: Identifier, required_amount: u64, identity_min_offer: Option, identity_max_offer: Option, @@ -41,7 +38,6 @@ impl IdentityHasNotAgreedToPayRequiredTokenAmountError { ) -> Self { Self { token_id, - identity_id, required_amount, identity_min_offer, identity_max_offer, @@ -53,10 +49,6 @@ impl IdentityHasNotAgreedToPayRequiredTokenAmountError { &self.token_id } - pub fn identity_id(&self) -> &Identifier { - &self.identity_id - } - pub fn required_amount(&self) -> u64 { self.required_amount } diff --git a/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs new file mode 100644 index 00000000000..6bfd5aa1f10 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs @@ -0,0 +1,99 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::ProtocolError; +use crate::data_contract::TokenContractPosition; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; + +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize)] +#[platform_serialize(unversioned)] +pub struct IdentityTryingToPayWithWrongTokenError { + expected_contract_id: Option, + expected_token_contract_position: TokenContractPosition, + expected_token_id: Identifier, + + actual_contract_id: Option, + actual_token_contract_position: TokenContractPosition, + actual_token_id: Identifier, +} + +impl IdentityTryingToPayWithWrongTokenError { + #[allow(clippy::too_many_arguments)] + pub fn new( + expected_contract_id: Option, + expected_token_contract_position: TokenContractPosition, + expected_token_id: Identifier, + actual_contract_id: Option, + actual_token_contract_position: TokenContractPosition, + actual_token_id: Identifier, + ) -> Self { + Self { + expected_contract_id, + expected_token_contract_position, + expected_token_id, + actual_contract_id, + actual_token_contract_position, + actual_token_id, + } + } + + pub fn expected_contract_id(&self) -> Option { + self.expected_contract_id.clone() + } + + pub fn expected_token_contract_position(&self) -> TokenContractPosition { + self.expected_token_contract_position + } + + pub fn expected_token_id(&self) -> &Identifier { + &self.expected_token_id + } + + pub fn actual_contract_id(&self) -> Option { + self.actual_contract_id.clone() + } + + pub fn actual_token_contract_position(&self) -> TokenContractPosition { + self.actual_token_contract_position + } + + pub fn actual_token_id(&self) -> &Identifier { + &self.actual_token_id + } +} + +impl std::fmt::Display for IdentityTryingToPayWithWrongTokenError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let expected_contract_display = match &self.expected_contract_id { + Some(id) => format!("{}", id), + None => "Not Expected".to_string(), + }; + + let actual_contract_display = match &self.actual_contract_id { + Some(id) => format!("{}", id), + None => "Not Set".to_string(), + }; + + write!( + f, + "Identity is trying to pay with the wrong token: \ +expected contract ID: {}, position: {}, token ID: {}; \ +actual contract ID: {}, position: {}, token ID: {}", + expected_contract_display, + self.expected_token_contract_position, + self.expected_token_id, + actual_contract_display, + self.actual_token_contract_position, + self.actual_token_id, + ) + } +} + +impl std::error::Error for IdentityTryingToPayWithWrongTokenError {} + +impl From for ConsensusError { + fn from(err: IdentityTryingToPayWithWrongTokenError) -> Self { + Self::StateError(StateError::IdentityTryingToPayWithWrongTokenError(err)) + } +} \ No newline at end of file diff --git a/packages/rs-dpp/src/errors/consensus/state/token/mod.rs b/packages/rs-dpp/src/errors/consensus/state/token/mod.rs index 7a733641dc8..afd476178c6 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/mod.rs @@ -20,6 +20,7 @@ mod token_transfer_recipient_identity_not_exist_error; mod unauthorized_token_action_error; mod identity_has_not_agreed_to_pay_required_token_amount_error; mod required_token_payment_info_not_set_error; +mod identity_trying_to_pay_with_wrong_token_error; pub use identity_does_not_have_enough_token_balance_error::*; pub use identity_token_account_already_frozen_error::*; @@ -43,3 +44,4 @@ pub use token_transfer_recipient_identity_not_exist_error::*; pub use unauthorized_token_action_error::*; pub use identity_has_not_agreed_to_pay_required_token_amount_error::*; pub use required_token_payment_info_not_set_error::*; +pub use identity_trying_to_pay_with_wrong_token_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs index ada9b37eb51..800bc742f94 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs @@ -10,27 +10,23 @@ use thiserror::Error; Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] #[error( - "Required token payment info not set for identity {} on token {} (action: {})", - identity_id, + "Required token payment info not set on token {} (action: {})", token_id, action )] #[platform_serialize(unversioned)] pub struct RequiredTokenPaymentInfoNotSetError { token_id: Identifier, - identity_id: Identifier, action: String, } impl RequiredTokenPaymentInfoNotSetError { pub fn new( token_id: Identifier, - identity_id: Identifier, action: String, ) -> Self { Self { token_id, - identity_id, action, } } @@ -39,10 +35,6 @@ impl RequiredTokenPaymentInfoNotSetError { &self.token_id } - pub fn identity_id(&self) -> &Identifier { - &self.identity_id - } - pub fn action(&self) -> &str { &self.action } diff --git a/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs new file mode 100644 index 00000000000..a4e097344d9 --- /dev/null +++ b/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs @@ -0,0 +1 @@ +pub mod v0; \ No newline at end of file diff --git a/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs new file mode 100644 index 00000000000..146618714d3 --- /dev/null +++ b/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs @@ -0,0 +1,31 @@ +use platform_value::Identifier; +use crate::balances::credits::TokenAmount; +use crate::data_contract::TokenContractPosition; +use crate::tokens::calculate_token_id; +use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; + +pub trait TokenPaymentInfoMethodsV0: TokenPaymentInfoAccessorsV0 { + fn is_valid_for_required_cost(&self, required_cost: TokenAmount) -> bool { + if let Some(min_cost) = self.minimum_token_cost() { + if required_cost < min_cost { + return false; + } + } + + if let Some(max_cost) = self.maximum_token_cost() { + if required_cost > max_cost { + return false; + } + } + + true + } + + fn matches_token_contract(&self, contract_id: &Option, token_contract_position: TokenContractPosition) -> bool { + self.payment_token_contract_id_ref() == contract_id && self.token_contract_position() == token_contract_position + } + + fn token_id(&self, current_contract_id: Identifier) -> Identifier { + calculate_token_id(self.payment_token_contract_id().unwrap_or(current_contract_id).as_bytes(), self.token_contract_position()).into() + } +} \ No newline at end of file diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs index bcc1ae48e73..4806df4299b 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -7,13 +7,16 @@ use crate::ProtocolError; use bincode_derive::{Decode, Encode}; use derive_more::{Display, From}; use platform_value::btreemap_extensions::BTreeValueMapHelper; -use platform_value::{Identifier, Value}; +use platform_value::{Error, Identifier, Value}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use crate::tokens::token_payment_info::methods::v0::TokenPaymentInfoMethodsV0; pub mod v0; +pub mod methods; -#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Display, From)] +#[derive(Debug, Clone, Copy, Encode, Decode, PlatformDeserialize, PlatformSerialize, PartialEq, Display, From)] #[cfg_attr( feature = "state-transition-serde-conversion", derive(Serialize, Deserialize) @@ -23,6 +26,10 @@ pub enum TokenPaymentInfo { V0(TokenPaymentInfoV0), } +impl TokenPaymentInfoMethodsV0 for TokenPaymentInfo { + +} + impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfo { // Getters fn payment_token_contract_id(&self) -> Option { @@ -114,3 +121,10 @@ impl TryFrom> for TokenPaymentInfo { } } } + +impl TryFrom for Value { + type Error = Error; + fn try_from(value: TokenPaymentInfo) -> Result { + platform_value::to_value(value) + } +} diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs index 169a62ccf85..3ab4c93d9ab 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs @@ -1,10 +1,12 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::DocumentType; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionV0}; impl DocumentBaseTransitionAction { @@ -13,14 +15,16 @@ impl DocumentBaseTransitionAction { value: DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option, - ) -> Result { + action: &str, + ) -> Result, Error> { Ok( DocumentBaseTransitionActionV0::try_from_base_transition_with_contract_lookup( value, get_data_contract, get_token_cost, + action, )? - .into(), + .map(|v0| v0.into()), ) } @@ -29,14 +33,16 @@ impl DocumentBaseTransitionAction { value: &DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option, - ) -> Result { + action: &str, + ) -> Result, Error> { Ok( DocumentBaseTransitionActionV0::try_from_borrowed_base_transition_with_contract_lookup( value, get_data_contract, get_token_cost, + action, )? - .into(), + .map(|v0| v0.into()), ) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs index 6d2a54f1664..21215cb2b1e 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs @@ -2,7 +2,10 @@ use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::DocumentType; use dpp::platform_value::Identifier; use std::sync::Arc; - +use dpp::consensus::ConsensusError; +use dpp::consensus::state::state_error::StateError; +use dpp::consensus::state::token::{IdentityHasNotAgreedToPayRequiredTokenAmountError, IdentityTryingToPayWithWrongTokenError, RequiredTokenPaymentInfoNotSetError}; +use dpp::prelude::ConsensusValidationResult; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use dpp::state_transition::batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; @@ -11,7 +14,9 @@ use dpp::tokens::calculate_token_id; use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; use dpp::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; +use dpp::tokens::token_payment_info::methods::v0::TokenPaymentInfoMethodsV0; use crate::drive::contract::DataContractFetchInfo; +use crate::error::Error; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionV0; impl DocumentBaseTransitionActionV0 { @@ -20,13 +25,15 @@ impl DocumentBaseTransitionActionV0 { value: DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option, - ) -> Result { + action: &str, + ) -> Result, Error> { let data_contract_id = value.data_contract_id(); let data_contract = get_data_contract(data_contract_id)?; let document_type = data_contract .contract .document_type_borrowed_for_name(value.document_type_name().as_str())?; - let token_cost = get_token_cost(document_type).map( + let document_action_token_cost = get_token_cost(document_type); + let token_cost = document_action_token_cost.map( |DocumentActionTokenCost { contract_id, token_contract_position, @@ -43,6 +50,47 @@ impl DocumentBaseTransitionActionV0 { ) }, ); + if let Some(document_action_token_cost) = document_action_token_cost { + let Some(token_payment_info) = value.token_payment_info_ref() else { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::RequiredTokenPaymentInfoNotSetError( + RequiredTokenPaymentInfoNotSetError::new( + token_cost.expect("expected token cost").0, + action.to_string(), + ), + )), + )); + }; + // Let's see that the user agreed to pay using the correct token + if !token_payment_info.matches_token_contract(&document_action_token_cost.contract_id, document_action_token_cost.token_contract_position) { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::IdentityTryingToPayWithWrongTokenError( + IdentityTryingToPayWithWrongTokenError::new( + document_action_token_cost.contract_id, + document_action_token_cost.token_contract_position, + token_cost.expect("expected token cost").0, + token_payment_info.payment_token_contract_id(), + token_payment_info.token_contract_position(), + token_payment_info.token_id(data_contract_id) + ), + )), + )); + } + // Let's see that the user agreed to pay the required amount + if !token_payment_info.is_valid_for_required_cost(document_action_token_cost.token_amount) { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( + IdentityHasNotAgreedToPayRequiredTokenAmountError::new( + token_cost.expect("expected token cost").0, + document_action_token_cost.token_amount, + token_payment_info.minimum_token_cost(), + token_payment_info.maximum_token_cost(), + action.to_string(), + ), + )), + )); + } + } let gas_fees_paid_by = value .token_payment_info_ref() .as_ref() @@ -55,7 +103,7 @@ impl DocumentBaseTransitionActionV0 { data_contract, token_cost, gas_fees_paid_by, - }) + }.into()) } /// try from borrowed base transition with contract lookup @@ -63,13 +111,15 @@ impl DocumentBaseTransitionActionV0 { value: &DocumentBaseTransition, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, get_token_cost: impl Fn(&DocumentType) -> Option, - ) -> Result { + action: &str, + ) -> Result, Error> { let data_contract_id = value.data_contract_id(); let data_contract = get_data_contract(data_contract_id)?; let document_type = data_contract .contract .document_type_borrowed_for_name(value.document_type_name().as_str())?; - let token_cost = get_token_cost(document_type).map( + let document_action_token_cost = get_token_cost(document_type); + let token_cost = document_action_token_cost.map( |DocumentActionTokenCost { contract_id, token_contract_position, @@ -81,11 +131,52 @@ impl DocumentBaseTransitionActionV0 { contract_id.unwrap_or(data_contract_id).as_bytes(), token_contract_position, ) - .into(), + .into(), token_amount, ) }, ); + if let Some(document_action_token_cost) = document_action_token_cost { + let Some(token_payment_info) = value.token_payment_info_ref() else { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::RequiredTokenPaymentInfoNotSetError( + RequiredTokenPaymentInfoNotSetError::new( + token_cost.expect("expected token cost").0, + action.to_string(), + ), + )), + )); + }; + // Let's see that the user agreed to pay using the correct token + if !token_payment_info.matches_token_contract(&document_action_token_cost.contract_id, document_action_token_cost.token_contract_position) { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::IdentityTryingToPayWithWrongTokenError( + IdentityTryingToPayWithWrongTokenError::new( + document_action_token_cost.contract_id, + document_action_token_cost.token_contract_position, + token_cost.expect("expected token cost").0, + token_payment_info.payment_token_contract_id(), + token_payment_info.token_contract_position(), + token_payment_info.token_id(data_contract_id) + ), + )), + )); + } + // Let's see that the user agreed to pay the required amount + if !token_payment_info.is_valid_for_required_cost(document_action_token_cost.token_amount) { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( + IdentityHasNotAgreedToPayRequiredTokenAmountError::new( + token_cost.expect("expected token cost").0, + document_action_token_cost.token_amount, + token_payment_info.minimum_token_cost(), + token_payment_info.maximum_token_cost(), + action.to_string(), + ), + )), + )); + } + } let gas_fees_paid_by = value .token_payment_info_ref() .as_ref() @@ -98,6 +189,6 @@ impl DocumentBaseTransitionActionV0 { data_contract, token_cost, gas_fees_paid_by, - }) + }.into()) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs index f1a3698fb57..d85ef310c9e 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs @@ -3,7 +3,7 @@ use dpp::fee::fee_result::FeeResult; use dpp::platform_value::Identifier; use grovedb::TransactionArg; use std::sync::Arc; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_create_transition::DocumentCreateTransition; use platform_version::version::PlatformVersion; @@ -17,9 +17,11 @@ impl DocumentCreateTransitionAction { /// from_document_create_transition_with_contract_lookup pub fn try_from_document_create_transition_with_contract_lookup( drive: &Drive, + owner_id: Identifier, transaction: TransactionArg, value: DocumentCreateTransition, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, ) -> Result< @@ -31,7 +33,7 @@ impl DocumentCreateTransitionAction { > { match value { DocumentCreateTransition::V0(v0) => { - DocumentCreateTransitionActionV0::try_from_document_create_transition_with_contract_lookup(drive, transaction, v0, block_info, get_data_contract, platform_version) + DocumentCreateTransitionActionV0::try_from_document_create_transition_with_contract_lookup(drive, owner_id, transaction, v0, block_info, user_fee_increase, get_data_contract, platform_version) } } } @@ -39,9 +41,11 @@ impl DocumentCreateTransitionAction { /// from_document_borrowed_create_transition_with_contract_lookup pub fn try_from_document_borrowed_create_transition_with_contract_lookup( drive: &Drive, + owner_id: Identifier, transaction: TransactionArg, value: &DocumentCreateTransition, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, ) -> Result< @@ -53,7 +57,7 @@ impl DocumentCreateTransitionAction { > { match value { DocumentCreateTransition::V0(v0) => { - DocumentCreateTransitionActionV0::try_from_borrowed_document_create_transition_with_contract_lookup(drive, transaction, v0, block_info, get_data_contract, platform_version) + DocumentCreateTransitionActionV0::try_from_borrowed_document_create_transition_with_contract_lookup(drive, owner_id, transaction, v0, block_info, user_fee_increase, get_data_contract, platform_version) } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs index 49590198b87..98fbc0c51bc 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs @@ -4,7 +4,7 @@ use dpp::fee::fee_result::FeeResult; use dpp::platform_value::Identifier; use grovedb::TransactionArg; use std::sync::Arc; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::document_create_transition::v0::DocumentCreateTransitionV0; use dpp::voting::vote_info_storage::contested_document_vote_poll_stored_info::ContestedDocumentVotePollStoredInfo; @@ -19,14 +19,17 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; use crate::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentCreateTransitionActionV0 { /// try from document create transition with contract lookup pub fn try_from_document_create_transition_with_contract_lookup( drive: &Drive, + owner_id: Identifier, transaction: TransactionArg, value: DocumentCreateTransitionV0, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, ) -> Result< @@ -42,12 +45,35 @@ impl DocumentCreateTransitionActionV0 { prefunded_voting_balance, .. } = value; - let base = DocumentBaseTransitionAction::try_from_base_transition_with_contract_lookup( + let base_action_validation_result = DocumentBaseTransitionAction::try_from_base_transition_with_contract_lookup( base, get_data_contract, |document_type| document_type.document_creation_token_cost(), + "create", )?; + let base = match base_action_validation_result.is_valid() { + true => base_action_validation_result.into_data()?, + false => { + let bump_action = + BumpIdentityDataContractNonceAction::from_document_base_transition( + base, + owner_id, + user_fee_increase, + ); + let batched_action = + BatchedTransitionAction::BumpIdentityDataContractNonce(bump_action); + + return Ok(( + ConsensusValidationResult::new_with_data_and_errors( + batched_action, + base_action_validation_result.errors, + ), + FeeResult::default(), + )); + } + }; + let document_type = base.document_type()?; let document_type_indexes = document_type.indexes(); diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs index ce33289bb79..4b26aea2be5 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs @@ -1,7 +1,7 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentDeleteTransition; use crate::drive::contract::DataContractFetchInfo; @@ -13,6 +13,8 @@ impl DocumentDeleteTransitionAction { /// from pub fn try_from_document_create_transition_with_contract_lookup( value: DocumentDeleteTransition, + owner_id: Identifier, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -22,13 +24,15 @@ impl DocumentDeleteTransitionAction { Error, > { match value { - DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_document_delete_transition_with_contract_lookup(v0, get_data_contract), + DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_document_delete_transition_with_contract_lookup(v0, owner_id, user_fee_increase, get_data_contract), } } /// from borrowed pub fn try_from_document_borrowed_create_transition_with_contract_lookup( value: &DocumentDeleteTransition, + owner_id: Identifier, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -38,7 +42,7 @@ impl DocumentDeleteTransitionAction { Error, > { match value { - DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_borrowed_document_delete_transition_with_contract_lookup(v0, get_data_contract), + DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_borrowed_document_delete_transition_with_contract_lookup(v0, owner_id, user_fee_increase, get_data_contract), } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs index 28bca387c52..0de569ed9c4 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs @@ -2,7 +2,7 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_delete_transition::DocumentDeleteTransitionV0; use crate::drive::contract::DataContractFetchInfo; @@ -16,6 +16,8 @@ impl DocumentDeleteTransitionActionV0 { /// try from pub fn try_from_document_delete_transition_with_contract_lookup( value: DocumentDeleteTransitionV0, + owner_id: Identifier, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -46,6 +48,8 @@ impl DocumentDeleteTransitionActionV0 { /// try from borrowed pub fn try_from_borrowed_document_delete_transition_with_contract_lookup( value: &DocumentDeleteTransitionV0, + owner_id: Identifier, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs index 1c300c8d661..bf54d862048 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs @@ -3,7 +3,7 @@ use dpp::document::Document; use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentPurchaseTransition; use crate::drive::contract::DataContractFetchInfo; @@ -15,9 +15,11 @@ impl DocumentPurchaseTransitionAction { /// try from borrowed pub fn try_from_borrowed_document_purchase_transition( document_purchase_transition: &DocumentPurchaseTransition, + owner_id: Identifier, original_document: Document, purchaser_id: Identifier, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -30,9 +32,11 @@ impl DocumentPurchaseTransitionAction { DocumentPurchaseTransition::V0(v0) => DocumentPurchaseTransitionActionV0::try_from_borrowed_document_purchase_transition( v0, + owner_id, original_document, purchaser_id, block_info, + user_fee_increase, get_data_contract, ), } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs index 1fa1fc1275c..17cc8452f79 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs @@ -5,7 +5,7 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_purchase_transition::DocumentPurchaseTransitionV0; use crate::drive::contract::DataContractFetchInfo; @@ -19,9 +19,11 @@ impl DocumentPurchaseTransitionActionV0 { /// try from borrowed pub fn try_from_borrowed_document_purchase_transition( document_purchase_transition: &DocumentPurchaseTransitionV0, + owner_id: Identifier, original_document: Document, purchaser_id: Identifier, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs index af2cd5594dc..79093e0c7ee 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs @@ -3,7 +3,7 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::fee::fee_result::FeeResult; use dpp::identity::TimestampMillis; -use dpp::prelude::{BlockHeight, ConsensusValidationResult, CoreBlockHeight}; +use dpp::prelude::{BlockHeight, ConsensusValidationResult, CoreBlockHeight, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentReplaceTransition; use crate::drive::contract::DataContractFetchInfo; @@ -16,6 +16,7 @@ impl DocumentReplaceTransitionAction { #[allow(clippy::too_many_arguments)] pub fn try_from_borrowed_document_replace_transition( document_replace_transition: &DocumentReplaceTransition, + owner_id: Identifier, originally_created_at: Option, originally_created_at_block_height: Option, originally_created_at_core_block_height: Option, @@ -23,6 +24,7 @@ impl DocumentReplaceTransitionAction { originally_transferred_at_block_height: Option, originally_transferred_at_core_block_height: Option, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -35,6 +37,7 @@ impl DocumentReplaceTransitionAction { DocumentReplaceTransition::V0(v0) => DocumentReplaceTransitionActionV0::try_from_borrowed_document_replace_transition( v0, + owner_id, originally_created_at, originally_created_at_block_height, originally_created_at_core_block_height, @@ -42,6 +45,7 @@ impl DocumentReplaceTransitionAction { originally_transferred_at_block_height, originally_transferred_at_core_block_height, block_info, + user_fee_increase, get_data_contract, ), } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs index 1e45432d8b8..da191ff47ac 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; use dpp::fee::fee_result::FeeResult; use dpp::identity::TimestampMillis; -use dpp::prelude::{BlockHeight, ConsensusValidationResult, CoreBlockHeight}; +use dpp::prelude::{BlockHeight, ConsensusValidationResult, CoreBlockHeight, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_replace_transition::DocumentReplaceTransitionV0; use crate::drive::contract::DataContractFetchInfo; @@ -20,6 +20,7 @@ impl DocumentReplaceTransitionActionV0 { #[allow(clippy::too_many_arguments)] pub fn try_from_borrowed_document_replace_transition( document_replace_transition: &DocumentReplaceTransitionV0, + owner_id: Identifier, originally_created_at: Option, originally_created_at_block_height: Option, originally_created_at_core_block_height: Option, @@ -27,6 +28,7 @@ impl DocumentReplaceTransitionActionV0 { originally_transferred_at_block_height: Option, originally_transferred_at_core_block_height: Option, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs index b7495b8fecb..cd4c9e9f50e 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs @@ -3,7 +3,7 @@ use dpp::document::Document; use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentTransferTransition; use crate::drive::contract::DataContractFetchInfo; @@ -15,8 +15,10 @@ impl DocumentTransferTransitionAction { /// try from borrowed pub fn try_from_borrowed_document_transfer_transition( document_transfer_transition: &DocumentTransferTransition, + owner_id: Identifier, original_document: Document, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -28,8 +30,10 @@ impl DocumentTransferTransitionAction { match document_transfer_transition { DocumentTransferTransition::V0(v0) => DocumentTransferTransitionActionV0::try_from_borrowed_document_transfer_transition( v0, + owner_id, original_document, block_info, + user_fee_increase, get_data_contract, ), } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs index 9d4fafaa4fa..5fddcec3a09 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs @@ -5,7 +5,7 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_transfer_transition::DocumentTransferTransitionV0; use crate::drive::contract::DataContractFetchInfo; @@ -19,8 +19,10 @@ impl DocumentTransferTransitionActionV0 { /// try from borrowed pub fn try_from_borrowed_document_transfer_transition( document_transfer_transition: &DocumentTransferTransitionV0, + owner_id: Identifier, original_document: Document, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs index 0d5f94b0111..03b1e93d597 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/transformer.rs @@ -3,7 +3,7 @@ use dpp::document::Document; use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::DocumentUpdatePriceTransition; use crate::drive::contract::DataContractFetchInfo; @@ -15,8 +15,10 @@ impl DocumentUpdatePriceTransitionAction { /// try from borrowed pub fn try_from_borrowed_document_update_price_transition( document_update_price_transition: &DocumentUpdatePriceTransition, + owner_id: Identifier, original_document: Document, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( @@ -28,8 +30,10 @@ impl DocumentUpdatePriceTransitionAction { match document_update_price_transition { DocumentUpdatePriceTransition::V0(v0) => DocumentUpdatePriceTransitionActionV0::try_from_borrowed_document_update_price_transition( v0, + owner_id, original_document, block_info, + user_fee_increase, get_data_contract, ), } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs index 217a8e1ee63..3ba651e5137 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs @@ -5,7 +5,7 @@ use dpp::platform_value::Identifier; use std::sync::Arc; use dpp::data_contract::document_type::accessors::DocumentTypeV1Getters; use dpp::fee::fee_result::FeeResult; -use dpp::prelude::ConsensusValidationResult; +use dpp::prelude::{ConsensusValidationResult, UserFeeIncrease}; use dpp::ProtocolError; use dpp::state_transition::batch_transition::batched_transition::document_update_price_transition::DocumentUpdatePriceTransitionV0; use crate::drive::contract::DataContractFetchInfo; @@ -19,8 +19,10 @@ impl DocumentUpdatePriceTransitionActionV0 { /// try from borrowed pub fn try_from_borrowed_document_update_price_transition( document_update_price_transition: &DocumentUpdatePriceTransitionV0, + owner_id: Identifier, original_document: Document, block_info: &BlockInfo, + user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, ) -> Result< ( From a968131637e7802e6a34e520fcea406ff6c358b4 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 09:50:30 +0700 Subject: [PATCH 06/18] added support for token payment info --- .../document/v0/document-meta.json | 57 +++ .../class_methods/try_from_schema/v1/mod.rs | 29 +- .../document/extended_document/accessors.rs | 2 +- .../src/document/extended_document/mod.rs | 2 +- .../src/document/extended_document/v0/mod.rs | 16 +- .../platform_serialization_conversion/mod.rs | 3 +- .../src/errors/consensus/basic/basic_error.rs | 13 +- .../consensus/basic/data_contract/mod.rs | 4 + ...ng_only_allowed_on_internal_token_error.rs | 76 +++ ...nown_document_action_token_effect_error.rs | 43 ++ packages/rs-dpp/src/errors/consensus/codes.rs | 2 + .../src/errors/consensus/state/state_error.rs | 4 +- ...reed_to_pay_required_token_amount_error.rs | 4 +- ...ty_trying_to_pay_with_wrong_token_error.rs | 4 +- .../src/errors/consensus/state/token/mod.rs | 12 +- ...quired_token_payment_info_not_set_error.rs | 12 +- packages/rs-dpp/src/errors/protocol_error.rs | 7 +- .../rs-dpp/src/tokens/gas_fees_paid_by.rs | 4 +- .../tokens/token_amount_on_contract_token.rs | 59 +++ .../tokens/token_payment_info/methods/mod.rs | 2 +- .../token_payment_info/methods/v0/mod.rs | 23 +- .../src/tokens/token_payment_info/mod.rs | 23 +- .../update_masternode_list/mod.rs | 2 +- .../state_v0/mod.rs | 33 +- .../data_triggers/triggers/dashpay/v0/mod.rs | 6 +- .../data_triggers/triggers/dpns/v0/mod.rs | 4 +- .../batch/tests/document/creation.rs | 228 ++++++++- .../batch/tests/document/deletion.rs | 6 +- .../batch/tests/document/mod.rs | 2 +- .../batch/tests/document/nft.rs | 2 +- .../batch/tests/document/replacement.rs | 2 +- .../batch/tests/document/transfer.rs | 2 +- .../batch/transformer/v0/mod.rs | 26 +- .../advanced_structure/v0/mod.rs | 12 +- .../data_contract_create/mod.rs | 474 ++++++++++++++++++ .../state_transition/state_transitions/mod.rs | 32 +- ...ard-game-in-game-currency-burn-tokens.json | 178 +++++++ ...rypto-card-game-use-external-currency.json | 2 +- .../document/document_create_transition.rs | 26 +- .../document/document_delete_transition.rs | 28 +- .../document/document_purchase_transition.rs | 28 +- .../document/document_replace_transition.rs | 28 +- .../document/document_transfer_transition.rs | 28 +- .../document_update_price_transition.rs | 28 +- .../document_base_transition_action/mod.rs | 3 +- .../transformer.rs | 20 +- .../document_base_transition_action/v0/mod.rs | 5 +- .../v0/transformer.rs | 122 +---- .../transformer.rs | 24 - .../v0/transformer.rs | 134 +---- .../transformer.rs | 18 - .../v0/transformer.rs | 76 ++- .../transformer.rs | 5 +- .../v0/transformer.rs | 31 +- .../transformer.rs | 5 +- .../v0/transformer.rs | 32 +- .../transformer.rs | 6 +- .../v0/transformer.rs | 32 +- .../v0/transformer.rs | 32 +- .../batch/batched_transition/mod.rs | 64 +-- .../transition/update_price_of_document.rs | 10 +- packages/wasm-dpp/src/document/factory.rs | 9 +- 62 files changed, 1688 insertions(+), 518 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/token_payment_by_burning_only_allowed_on_internal_token_error.rs create mode 100644 packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_document_action_token_effect_error.rs create mode 100644 packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency-burn-tokens.json diff --git a/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json b/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json index 80d20a3f775..b34388a310b 100644 --- a/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json +++ b/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json @@ -287,6 +287,39 @@ } } ] + }, + "documentActionTokenCost": { + "type": "object", + "properties": { + "contractId": { + "type": "array", + "contentMediaType": "application/x.dash.dpp.identifier", + "byteArray": true, + "minItems": 32, + "maxItems": 32 + }, + "tokenPosition": { + "type": "integer", + "minimum": 0 + }, + "amount": { + "type": "integer", + "minimum": 0 + }, + "effect": { + "type": "integer", + "description": "0 - TransferTokenToContractOwner (default), 1 - Burn" + }, + "gasFeesPaidBy": { + "type": "integer", + "description": "0 - DocumentOwner (default), 1 - ContractOwner, 2 - PreferContractOwner" + } + }, + "required": [ + "tokenPosition", + "amount" + ], + "additionalProperties": false } }, "properties": { @@ -453,6 +486,30 @@ ], "description": "Key requirements. 0 - Unique Non Replaceable, 1 - Multiple, 2 - Multiple with reference to latest key." }, + "tokenCost": { + "type": "object", + "properties": { + "create": { + "$ref": "#/$defs/documentActionTokenCost" + }, + "replace": { + "$ref": "#/$defs/documentActionTokenCost" + }, + "delete": { + "$ref": "#/$defs/documentActionTokenCost" + }, + "transfer": { + "$ref": "#/$defs/documentActionTokenCost" + }, + "update_price": { + "$ref": "#/$defs/documentActionTokenCost" + }, + "purchase": { + "$ref": "#/$defs/documentActionTokenCost" + } + }, + "additionalProperties": false + }, "properties": { "type": "object", "additionalProperties": { diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs index 8661b979813..b39f88d383d 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs @@ -26,6 +26,7 @@ use crate::consensus::basic::data_contract::ContestedUniqueIndexOnMutableDocumen use crate::consensus::basic::data_contract::ContestedUniqueIndexWithUniqueIndexError; #[cfg(any(test, feature = "validation"))] use crate::consensus::basic::data_contract::InvalidDocumentTypeNameError; +use crate::consensus::basic::data_contract::TokenPaymentByBurningOnlyAllowedOnInternalTokenError; #[cfg(feature = "validation")] use crate::consensus::basic::document::MissingPositionsInDocumentTypePropertiesError; #[cfg(feature = "validation")] @@ -51,7 +52,9 @@ use crate::data_contract::storage_requirements::keys_for_document_type::StorageK use crate::data_contract::TokenContractPosition; use crate::identity::SecurityLevel; use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; -use crate::tokens::token_amount_on_contract_token::DocumentActionTokenCost; +use crate::tokens::token_amount_on_contract_token::{ + DocumentActionTokenCost, DocumentActionTokenEffect, +}; #[cfg(feature = "validation")] use crate::validation::meta_validators::DOCUMENT_META_SCHEMA_V0; use crate::validation::operations::ProtocolValidationOperation; @@ -558,6 +561,29 @@ impl DocumentTypeV1 { action_cost.get_integer::("tokenPosition")?; // Extract the token amount. let token_amount = action_cost.get_integer::("amount")?; + // Extract the token effect + let effect = action_cost + .get_optional_integer::("effect")? + .map(|int| int.try_into()) + .transpose()? + .unwrap_or(DocumentActionTokenEffect::TransferTokenToContractOwner); + + // If contractId is present and user tries to burn, bail out: + if contract_id.is_some() && effect == DocumentActionTokenEffect::BurnToken { + return Err(ProtocolError::ConsensusError( + ConsensusError::BasicError( + BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError( + TokenPaymentByBurningOnlyAllowedOnInternalTokenError::new( + contract_id.unwrap(), + token_contract_position, + key.to_string(), + ), + ), + ) + .into(), + )); + } + // Extract an optional string and map it to the enum, defaulting if missing or unrecognized. let gas_fees_paid_by = action_cost .get_optional_integer::("gasFeesPaidBy")? @@ -569,6 +595,7 @@ impl DocumentTypeV1 { contract_id, token_contract_position, token_amount, + effect, gas_fees_paid_by, }) }) diff --git a/packages/rs-dpp/src/document/extended_document/accessors.rs b/packages/rs-dpp/src/document/extended_document/accessors.rs index c88e4ceab91..c20951f83ac 100644 --- a/packages/rs-dpp/src/document/extended_document/accessors.rs +++ b/packages/rs-dpp/src/document/extended_document/accessors.rs @@ -4,10 +4,10 @@ use crate::document::{Document, ExtendedDocument}; use crate::identity::TimestampMillis; use crate::metadata::Metadata; use crate::prelude::{BlockHeight, CoreBlockHeight, Revision}; +use crate::tokens::token_payment_info::TokenPaymentInfo; use crate::ProtocolError; use platform_value::{Bytes32, Identifier, Value}; use std::collections::BTreeMap; -use crate::tokens::token_payment_info::TokenPaymentInfo; impl ExtendedDocument { /// Returns an immutable reference to the properties of the document. diff --git a/packages/rs-dpp/src/document/extended_document/mod.rs b/packages/rs-dpp/src/document/extended_document/mod.rs index 4d967024120..83f1eb3c3df 100644 --- a/packages/rs-dpp/src/document/extended_document/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/mod.rs @@ -20,6 +20,7 @@ use crate::document::extended_document::v0::ExtendedDocumentV0; use crate::document::serialization_traits::DocumentJsonMethodsV0; #[cfg(feature = "validation")] use crate::validation::SimpleConsensusValidationResult; +use derive_more::From; use platform_value::Value; use platform_version::version::PlatformVersion; use platform_versioning::PlatformVersioned; @@ -27,7 +28,6 @@ use platform_versioning::PlatformVersioned; use serde_json::Value as JsonValue; #[cfg(feature = "document-value-conversion")] use std::collections::BTreeMap; -use derive_more::From; #[derive(Debug, Clone, PlatformVersioned, From)] pub enum ExtendedDocument { diff --git a/packages/rs-dpp/src/document/extended_document/v0/mod.rs b/packages/rs-dpp/src/document/extended_document/v0/mod.rs index df61308a6bf..0b4140b8a51 100644 --- a/packages/rs-dpp/src/document/extended_document/v0/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/v0/mod.rs @@ -40,6 +40,7 @@ use crate::document::serialization_traits::DocumentJsonMethodsV0; #[cfg(feature = "document-value-conversion")] use crate::document::serialization_traits::DocumentPlatformValueMethodsV0; use crate::document::serialization_traits::ExtendedDocumentPlatformConversionMethodsV0; +use crate::tokens::token_payment_info::TokenPaymentInfo; #[cfg(feature = "validation")] use crate::validation::SimpleConsensusValidationResult; #[cfg(feature = "document-json-conversion")] @@ -47,7 +48,6 @@ use platform_value::converter::serde_json::BTreeValueJsonConverter; use platform_version::version::PlatformVersion; #[cfg(feature = "document-json-conversion")] use serde_json::Value as JsonValue; -use crate::tokens::token_payment_info::TokenPaymentInfo; /// The `ExtendedDocumentV0` struct represents the data provided by the platform in response to a query. #[derive(Debug, Clone)] @@ -309,8 +309,10 @@ impl ExtendedDocumentV0 { property_names::TOKEN_PAYMENT_INFO, ) .ok() - .flatten().map(|map| map.try_into()).transpose()?; - + .flatten() + .map(|map| map.try_into()) + .transpose()?; + let document_type_name = properties .remove_string(property_names::DOCUMENT_TYPE_NAME) .map_err(ProtocolError::ValueError)?; @@ -366,7 +368,9 @@ impl ExtendedDocumentV0 { property_names::TOKEN_PAYMENT_INFO, ) .ok() - .flatten().map(|map| map.try_into()).transpose()?; + .flatten() + .map(|map| map.try_into()) + .transpose()?; let document_type = data_contract.document_type_for_name(document_type_name.as_str())?; @@ -426,7 +430,7 @@ impl ExtendedDocumentV0 { JsonValue::String(bs58::encode(self.data_contract_id.to_buffer()).into_string()), ); if let Some(token_payment_info) = self.token_payment_info { - let value : Value = token_payment_info.try_into()?; + let value: Value = token_payment_info.try_into()?; value_mut.insert( property_names::TOKEN_PAYMENT_INFO.to_string(), value.try_into_validating_json()?, @@ -558,4 +562,4 @@ impl ExtendedDocumentV0 { platform_version, ) } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs b/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs index e3a112c47e9..40fc1025a1b 100644 --- a/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs +++ b/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs @@ -110,8 +110,9 @@ mod tests { use crate::data_contract::accessors::v0::DataContractV0Getters; use crate::data_contract::document_type::random_document::CreateRandomDocument; use crate::document::serialization_traits::DocumentPlatformConversionMethodsV0; - use crate::document::Document; + use crate::document::{Document, DocumentV0Setters}; use crate::tests::json_document::json_document_to_contract; + use platform_value::Value; use platform_version::version::PlatformVersion; #[test] diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index b3f75578071..9c883845be4 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -4,7 +4,6 @@ use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use thiserror::Error; use crate::consensus::basic::data_contract::data_contract_max_depth_exceed_error::DataContractMaxDepthExceedError; -use crate::consensus::basic::data_contract::InvalidJsonSchemaRefError; use crate::consensus::basic::data_contract::{ ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractHaveNewUniqueIndexError, DataContractImmutablePropertiesUpdateError, @@ -27,6 +26,10 @@ use crate::consensus::basic::data_contract::{ UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError, }; +use crate::consensus::basic::data_contract::{ + InvalidJsonSchemaRefError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, + UnknownDocumentActionTokenEffectError, +}; use crate::consensus::basic::decode::{ ProtocolVersionParsingError, SerializedObjectParsingError, VersionError, }; @@ -504,6 +507,14 @@ pub enum BasicError { #[error(transparent)] UnknownGasFeesPaidByError(UnknownGasFeesPaidByError), + + #[error(transparent)] + UnknownDocumentActionTokenEffectError(UnknownDocumentActionTokenEffectError), + + #[error(transparent)] + TokenPaymentByBurningOnlyAllowedOnInternalTokenError( + TokenPaymentByBurningOnlyAllowedOnInternalTokenError, + ), } impl From for ConsensusError { diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs index 250cd412b5b..cb59f46d74d 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -34,8 +34,10 @@ mod invalid_token_distribution_function_invalid_parameter_tuple_error; mod non_contiguous_contract_group_positions_error; mod non_contiguous_contract_token_positions_error; mod system_property_index_already_present_error; +mod token_payment_by_burning_only_allowed_on_internal_token_error; mod undefined_index_property_error; mod unique_indices_limit_reached_error; +mod unknown_document_action_token_effect_error; mod unknown_document_creation_restriction_mode_error; mod unknown_gas_fees_paid_by_error; mod unknown_security_level_error; @@ -82,6 +84,8 @@ pub use invalid_token_distribution_function_invalid_parameter_error::*; pub use invalid_token_distribution_function_invalid_parameter_tuple_error::*; pub use non_contiguous_contract_group_positions_error::*; pub use non_contiguous_contract_token_positions_error::*; +pub use token_payment_by_burning_only_allowed_on_internal_token_error::*; +pub use unknown_document_action_token_effect_error::*; pub use unknown_document_creation_restriction_mode_error::*; pub use unknown_gas_fees_paid_by_error::*; pub use unknown_security_level_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/token_payment_by_burning_only_allowed_on_internal_token_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/token_payment_by_burning_only_allowed_on_internal_token_error.rs new file mode 100644 index 00000000000..65fcd8ed0a7 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/token_payment_by_burning_only_allowed_on_internal_token_error.rs @@ -0,0 +1,76 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::data_contract::TokenContractPosition; +use crate::tokens::calculate_token_id; +use crate::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use std::fmt; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[platform_serialize(unversioned)] +pub struct TokenPaymentByBurningOnlyAllowedOnInternalTokenError { + external_token_contract_id: Identifier, + external_token_contract_token_position: TokenContractPosition, + action: String, +} + +impl TokenPaymentByBurningOnlyAllowedOnInternalTokenError { + pub fn new( + external_token_contract_id: Identifier, + external_token_contract_token_position: TokenContractPosition, + action: String, + ) -> Self { + Self { + external_token_contract_id, + external_token_contract_token_position, + action, + } + } + + pub fn external_token_contract_id(&self) -> Identifier { + self.external_token_contract_id + } + + pub fn external_token_id(&self) -> Identifier { + calculate_token_id( + self.external_token_contract_id.as_bytes(), + self.external_token_contract_token_position, + ) + .into() + } + + pub fn external_token_contract_token_position(&self) -> TokenContractPosition { + self.external_token_contract_token_position + } + + pub fn action(&self) -> &str { + self.action.as_str() + } +} + +// Custom Display implementation to include external_token_id +impl fmt::Display for TokenPaymentByBurningOnlyAllowedOnInternalTokenError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Token payments by burning only allowed on internal tokens. \ +Trying to register a contract that burns tokens with id {} from contract {} \ +at position {} for action '{}'.", + self.external_token_id(), + self.external_token_contract_id, + self.external_token_contract_token_position, + self.action + ) + } +} + +impl From for ConsensusError { + fn from(err: TokenPaymentByBurningOnlyAllowedOnInternalTokenError) -> Self { + Self::BasicError(BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_document_action_token_effect_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_document_action_token_effect_error.rs new file mode 100644 index 00000000000..f7820172795 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/unknown_document_action_token_effect_error.rs @@ -0,0 +1,43 @@ +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error( + "Unrecognized document action token effect: allowed {:?}, got {}", + allowed_values, + received +)] +#[platform_serialize(unversioned)] +pub struct UnknownDocumentActionTokenEffectError { + allowed_values: Vec, + received: u64, +} + +impl UnknownDocumentActionTokenEffectError { + pub fn new(allowed_values: Vec, received: u64) -> Self { + Self { + allowed_values, + received, + } + } + + pub fn allowed_values(&self) -> &[u8] { + &self.allowed_values + } + + pub fn received(&self) -> u64 { + self.received + } +} + +impl From for ConsensusError { + fn from(err: UnknownDocumentActionTokenEffectError) -> Self { + Self::BasicError(BasicError::UnknownDocumentActionTokenEffectError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 016509ac8e5..f58b0f07ccb 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -104,6 +104,8 @@ impl ErrorWithCode for BasicError { Self::InvalidTokenDistributionFunctionIncoherenceError(_) => 10257, Self::MissingDefaultLocalizationError(_) => 10258, Self::UnknownGasFeesPaidByError(_) => 10259, + Self::UnknownDocumentActionTokenEffectError(_) => 10260, + Self::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(_) => 10261, // Group Errors: 10350-10399 Self::GroupPositionDoesNotExistError(_) => 10350, diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index c98088e2539..e4b23ef0eb9 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -280,7 +280,9 @@ pub enum StateError { PreProgrammedDistributionTimestampInPastError(PreProgrammedDistributionTimestampInPastError), #[error(transparent)] - IdentityHasNotAgreedToPayRequiredTokenAmountError(IdentityHasNotAgreedToPayRequiredTokenAmountError), + IdentityHasNotAgreedToPayRequiredTokenAmountError( + IdentityHasNotAgreedToPayRequiredTokenAmountError, + ), #[error(transparent)] RequiredTokenPaymentInfoNotSetError(RequiredTokenPaymentInfoNotSetError), diff --git a/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs index 28a5c7128ab..1096cbf929e 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/identity_has_not_agreed_to_pay_required_token_amount_error.rs @@ -1,7 +1,7 @@ +use crate::balances::credits::TokenAmount; use crate::consensus::state::state_error::StateError; use crate::consensus::ConsensusError; use crate::ProtocolError; -use crate::balances::credits::TokenAmount; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use platform_value::Identifier; @@ -70,4 +70,4 @@ impl From for ConsensusError fn from(err: IdentityHasNotAgreedToPayRequiredTokenAmountError) -> Self { Self::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError(err)) } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs index 6bfd5aa1f10..ea6c8ebf162 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs @@ -1,7 +1,7 @@ use crate::consensus::state::state_error::StateError; use crate::consensus::ConsensusError; -use crate::ProtocolError; use crate::data_contract::TokenContractPosition; +use crate::ProtocolError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use platform_value::Identifier; @@ -96,4 +96,4 @@ impl From for ConsensusError { fn from(err: IdentityTryingToPayWithWrongTokenError) -> Self { Self::StateError(StateError::IdentityTryingToPayWithWrongTokenError(err)) } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/errors/consensus/state/token/mod.rs b/packages/rs-dpp/src/errors/consensus/state/token/mod.rs index afd476178c6..bd63f021a6c 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/mod.rs @@ -1,7 +1,9 @@ mod identity_does_not_have_enough_token_balance_error; +mod identity_has_not_agreed_to_pay_required_token_amount_error; mod identity_token_account_already_frozen_error; mod identity_token_account_frozen_error; mod identity_token_account_not_frozen_error; +mod identity_trying_to_pay_with_wrong_token_error; mod invalid_group_position_error; mod invalid_token_claim_no_current_rewards; mod invalid_token_claim_property_mismatch; @@ -11,6 +13,7 @@ mod new_authorized_action_taker_identity_does_not_exist_error; mod new_authorized_action_taker_main_group_not_set_error; mod new_tokens_destination_identity_does_not_exist_error; mod pre_programmed_distribution_timestamp_in_past_error; +mod required_token_payment_info_not_set_error; mod token_already_paused_error; mod token_is_paused_error; mod token_mint_past_max_supply_error; @@ -18,14 +21,13 @@ mod token_not_paused_error; mod token_setting_max_supply_to_less_than_current_supply_error; mod token_transfer_recipient_identity_not_exist_error; mod unauthorized_token_action_error; -mod identity_has_not_agreed_to_pay_required_token_amount_error; -mod required_token_payment_info_not_set_error; -mod identity_trying_to_pay_with_wrong_token_error; pub use identity_does_not_have_enough_token_balance_error::*; +pub use identity_has_not_agreed_to_pay_required_token_amount_error::*; pub use identity_token_account_already_frozen_error::*; pub use identity_token_account_frozen_error::*; pub use identity_token_account_not_frozen_error::*; +pub use identity_trying_to_pay_with_wrong_token_error::*; pub use invalid_group_position_error::*; pub use invalid_token_claim_no_current_rewards::*; pub use invalid_token_claim_property_mismatch::*; @@ -35,6 +37,7 @@ pub use new_authorized_action_taker_identity_does_not_exist_error::*; pub use new_authorized_action_taker_main_group_not_set_error::*; pub use new_tokens_destination_identity_does_not_exist_error::*; pub use pre_programmed_distribution_timestamp_in_past_error::*; +pub use required_token_payment_info_not_set_error::*; pub use token_already_paused_error::*; pub use token_is_paused_error::*; pub use token_mint_past_max_supply_error::*; @@ -42,6 +45,3 @@ pub use token_not_paused_error::*; pub use token_setting_max_supply_to_less_than_current_supply_error::*; pub use token_transfer_recipient_identity_not_exist_error::*; pub use unauthorized_token_action_error::*; -pub use identity_has_not_agreed_to_pay_required_token_amount_error::*; -pub use required_token_payment_info_not_set_error::*; -pub use identity_trying_to_pay_with_wrong_token_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs index 800bc742f94..f1a76fe8ab1 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/required_token_payment_info_not_set_error.rs @@ -21,14 +21,8 @@ pub struct RequiredTokenPaymentInfoNotSetError { } impl RequiredTokenPaymentInfoNotSetError { - pub fn new( - token_id: Identifier, - action: String, - ) -> Self { - Self { - token_id, - action, - } + pub fn new(token_id: Identifier, action: String) -> Self { + Self { token_id, action } } pub fn token_id(&self) -> &Identifier { @@ -44,4 +38,4 @@ impl From for ConsensusError { fn from(err: RequiredTokenPaymentInfoNotSetError) -> Self { Self::StateError(StateError::RequiredTokenPaymentInfoNotSetError(err)) } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 4b6b74f4d28..e9acd8d26a3 100644 --- a/packages/rs-dpp/src/errors/protocol_error.rs +++ b/packages/rs-dpp/src/errors/protocol_error.rs @@ -284,9 +284,12 @@ pub enum ProtocolError { #[error("missing epoch info: {0}")] MissingEpochInfo(String), - + #[error("Invalid BatchedTransitionAction variant: expected {expected}, found {found}")] - InvalidBatchedTransitionActionVariant { expected: &'static str, found: &'static str }, + InvalidBatchedTransitionActionVariant { + expected: &'static str, + found: &'static str, + }, } impl From<&str> for ProtocolError { diff --git a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs index 1f27b4cf02f..ba0644e7118 100644 --- a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs +++ b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs @@ -42,7 +42,7 @@ impl TryFrom for GasFeesPaidBy { 2 => Ok(GasFeesPaidBy::PreferContractOwner), value => Err(ProtocolError::ConsensusError( ConsensusError::BasicError(BasicError::UnknownGasFeesPaidByError( - UnknownGasFeesPaidByError::new(vec![0, 1], value as u64), + UnknownGasFeesPaidByError::new(vec![0, 1, 2], value as u64), )) .into(), )), @@ -58,7 +58,7 @@ impl TryFrom for GasFeesPaidBy { .map_err(|_| { ProtocolError::ConsensusError( ConsensusError::BasicError(BasicError::UnknownGasFeesPaidByError( - UnknownGasFeesPaidByError::new(vec![0, 1], value), + UnknownGasFeesPaidByError::new(vec![0, 1, 2], value), )) .into(), ) diff --git a/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs b/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs index 2bb05571cb8..4a8100f1207 100644 --- a/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs +++ b/packages/rs-dpp/src/tokens/token_amount_on_contract_token.rs @@ -1,8 +1,65 @@ use crate::balances::credits::TokenAmount; +use crate::consensus::basic::data_contract::UnknownDocumentActionTokenEffectError; +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; use crate::data_contract::TokenContractPosition; use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use crate::ProtocolError; use platform_value::Identifier; +#[derive(Debug, PartialEq, Clone, Copy, Default)] +pub enum DocumentActionTokenEffect { + /// When the document action occurs the token is transferred to the balance of the contract owner + #[default] + TransferTokenToContractOwner, + /// When the document action occurs the token is burned + /// This option is not available for external tokens. + BurnToken, +} + +impl From for u8 { + fn from(value: DocumentActionTokenEffect) -> Self { + match value { + DocumentActionTokenEffect::TransferTokenToContractOwner => 0, + DocumentActionTokenEffect::BurnToken => 1, + } + } +} + +impl TryFrom for DocumentActionTokenEffect { + type Error = ProtocolError; + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(DocumentActionTokenEffect::TransferTokenToContractOwner), + 1 => Ok(DocumentActionTokenEffect::BurnToken), + other => Err(ProtocolError::ConsensusError( + ConsensusError::BasicError(BasicError::UnknownDocumentActionTokenEffectError( + UnknownDocumentActionTokenEffectError::new(vec![0, 1], other as u64), + )) + .into(), + )), + } + } +} + +impl TryFrom for DocumentActionTokenEffect { + type Error = ProtocolError; + + fn try_from(value: u64) -> Result { + u8::try_from(value) + .map_err(|_| { + ProtocolError::ConsensusError( + ConsensusError::BasicError(BasicError::UnknownDocumentActionTokenEffectError( + UnknownDocumentActionTokenEffectError::new(vec![0, 1], value), + )) + .into(), + ) + })? + .try_into() + } +} + #[derive(Debug, PartialEq, Clone, Copy, Default)] pub struct DocumentActionTokenCost { /// If this is not set, it means that we are using our own contract id @@ -11,6 +68,8 @@ pub struct DocumentActionTokenCost { pub token_contract_position: TokenContractPosition, /// The amount pub token_amount: TokenAmount, + /// The amount + pub effect: DocumentActionTokenEffect, /// Who is paying for gas fees for this action pub gas_fees_paid_by: GasFeesPaidBy, } diff --git a/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs index a4e097344d9..2d24cd45f58 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/methods/mod.rs @@ -1 +1 @@ -pub mod v0; \ No newline at end of file +pub mod v0; diff --git a/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs index 146618714d3..a827088ce74 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/methods/v0/mod.rs @@ -1,8 +1,8 @@ -use platform_value::Identifier; use crate::balances::credits::TokenAmount; use crate::data_contract::TokenContractPosition; use crate::tokens::calculate_token_id; use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; +use platform_value::Identifier; pub trait TokenPaymentInfoMethodsV0: TokenPaymentInfoAccessorsV0 { fn is_valid_for_required_cost(&self, required_cost: TokenAmount) -> bool { @@ -20,12 +20,23 @@ pub trait TokenPaymentInfoMethodsV0: TokenPaymentInfoAccessorsV0 { true } - - fn matches_token_contract(&self, contract_id: &Option, token_contract_position: TokenContractPosition) -> bool { - self.payment_token_contract_id_ref() == contract_id && self.token_contract_position() == token_contract_position + + fn matches_token_contract( + &self, + contract_id: &Option, + token_contract_position: TokenContractPosition, + ) -> bool { + self.payment_token_contract_id_ref() == contract_id + && self.token_contract_position() == token_contract_position } fn token_id(&self, current_contract_id: Identifier) -> Identifier { - calculate_token_id(self.payment_token_contract_id().unwrap_or(current_contract_id).as_bytes(), self.token_contract_position()).into() + calculate_token_id( + self.payment_token_contract_id() + .unwrap_or(current_contract_id) + .as_bytes(), + self.token_contract_position(), + ) + .into() } -} \ No newline at end of file +} diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs index 4806df4299b..e4127bd0347 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -1,22 +1,33 @@ use crate::balances::credits::TokenAmount; use crate::data_contract::TokenContractPosition; use crate::tokens::gas_fees_paid_by::GasFeesPaidBy; +use crate::tokens::token_payment_info::methods::v0::TokenPaymentInfoMethodsV0; use crate::tokens::token_payment_info::v0::v0_accessors::TokenPaymentInfoAccessorsV0; use crate::tokens::token_payment_info::v0::TokenPaymentInfoV0; use crate::ProtocolError; use bincode_derive::{Decode, Encode}; use derive_more::{Display, From}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use platform_value::btreemap_extensions::BTreeValueMapHelper; use platform_value::{Error, Identifier, Value}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; -use crate::tokens::token_payment_info::methods::v0::TokenPaymentInfoMethodsV0; -pub mod v0; pub mod methods; +pub mod v0; -#[derive(Debug, Clone, Copy, Encode, Decode, PlatformDeserialize, PlatformSerialize, PartialEq, Display, From)] +#[derive( + Debug, + Clone, + Copy, + Encode, + Decode, + PlatformDeserialize, + PlatformSerialize, + PartialEq, + Display, + From, +)] #[cfg_attr( feature = "state-transition-serde-conversion", derive(Serialize, Deserialize) @@ -26,9 +37,7 @@ pub enum TokenPaymentInfo { V0(TokenPaymentInfoV0), } -impl TokenPaymentInfoMethodsV0 for TokenPaymentInfo { - -} +impl TokenPaymentInfoMethodsV0 for TokenPaymentInfo {} impl TokenPaymentInfoAccessorsV0 for TokenPaymentInfo { // Getters diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_list/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_list/mod.rs index e542bc7e8c4..f0de44e4709 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_list/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_list/mod.rs @@ -129,7 +129,7 @@ mod test { platform .core_rpc .expect_get_protx_diff_with_masternodes() - .returning(move |base_block, block| { + .returning(move |_base_block, block| { if block == 2128896 { let file_path = adjust_path_based_on_current_dir( "tests/supporting_files/mainnet_protx_list_diffs/1-2128896.json", diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_base_transaction_action/state_v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_base_transaction_action/state_v0/mod.rs index 33df1dcc541..d2485c577a7 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_base_transaction_action/state_v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_base_transaction_action/state_v0/mod.rs @@ -1,8 +1,9 @@ use dpp::block::block_info::BlockInfo; use dpp::consensus::ConsensusError; use dpp::consensus::state::state_error::StateError; -use dpp::consensus::state::token::IdentityDoesNotHaveEnoughTokenBalanceError; +use dpp::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError}; use dpp::identifier::Identifier; +use dpp::tokens::info::v0::IdentityTokenInfoV0Accessors; use dpp::validation::SimpleConsensusValidationResult; use drive::grovedb::TransactionArg; use drive::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; @@ -39,7 +40,35 @@ impl DocumentBaseTransitionActionStateValidationV0 for DocumentBaseTransitionAct // The following was introduced with tokens, since there are no token costs before v9 there was no reason to // create a new version for state verification - if let Some((token_id, cost_in_tokens)) = self.token_cost() { + if let Some((token_id, _, cost_in_tokens)) = self.token_cost() { + let (maybe_identity_token_info, fee_result) = + platform.drive.fetch_identity_token_info_with_costs( + token_id.to_buffer(), + owner_id.to_buffer(), + block_info, + true, + transaction, + platform_version, + )?; + + execution_context + .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + + if let Some(identity_token_info) = maybe_identity_token_info { + // if we have an info we need to make sure we are not frozen for this identity + if identity_token_info.frozen() { + return Ok(SimpleConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::IdentityTokenAccountFrozenError( + IdentityTokenAccountFrozenError::new( + token_id, + owner_id, + format!("Document {} token payment", transition_type), + ), + )), + )); + } + } + let (maybe_identity_token_balance, fee_result) = platform.drive.fetch_identity_token_balance_with_costs( token_id.to_buffer(), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs index 6448ab3c8cd..ad43302fbba 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dashpay/v0/mod.rs @@ -185,7 +185,7 @@ mod test { }; let result = create_contact_request_data_trigger( - &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { + &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, *owner_id, None, document_create_transition, &BlockInfo::default(), 0, |_identifier| { Ok(Arc::new(DataContractFetchInfo::dashpay_contract_fixture(protocol_version))) }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, @@ -308,7 +308,7 @@ mod test { let _dashpay_identity_id = data_trigger_context.owner_id.to_owned(); let result = create_contact_request_data_trigger( - &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { + &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, owner_id, None, document_create_transition, &BlockInfo::default(), 0, |_identifier| { Ok(Arc::new(DataContractFetchInfo::dashpay_contract_fixture(protocol_version))) }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, @@ -426,7 +426,7 @@ mod test { let _dashpay_identity_id = data_trigger_context.owner_id.to_owned(); let result = create_contact_request_data_trigger( - &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, document_create_transition, &BlockInfo::default(), |_identifier| { + &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, owner_id, None, document_create_transition, &BlockInfo::default(), 0, |_identifier| { Ok(Arc::new(DataContractFetchInfo::dashpay_contract_fixture(protocol_version))) }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs index 495786d8b60..e94ab7595b5 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/triggers/dpns/v0/mod.rs @@ -445,8 +445,8 @@ mod test { }; let result = create_domain_data_trigger_v0( - &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, None, - document_create_transition, &BlockInfo::default(), |_identifier| { + &DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(&platform.drive, owner_id, None, + document_create_transition, &BlockInfo::default(), 0, |_identifier| { Ok(Arc::new(DataContractFetchInfo::dpns_contract_fixture(platform_version.protocol_version))) }, platform_version).expect("expected to create action").0.into_data().expect("expected to be a valid transition").as_document_action().expect("expected document action"), &data_trigger_context, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 4eecede66a0..5b413b56e07 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -45,7 +45,7 @@ mod creation_tests { use dpp::tokens::token_payment_info::TokenPaymentInfo; use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; use crate::config::PlatformConfig; - use crate::execution::validation::state_transition::tests::{create_card_game_external_token_contract_with_owner_identity, create_token_contract_with_owner_identity}; + use crate::execution::validation::state_transition::tests::{create_card_game_external_token_contract_with_owner_identity, create_card_game_internal_token_contract_with_owner_identity_transfer_tokens, create_token_contract_with_owner_identity}; #[test] fn test_document_creation() { @@ -2469,7 +2469,7 @@ mod creation_tests { } #[test] - fn test_document_creation_paid_with_a_token() { + fn test_document_creation_paid_with_a_token_burn() { let platform_version = PlatformVersion::latest(); let mut platform = TestPlatformBuilder::new() .with_latest_protocol_version() @@ -2485,7 +2485,7 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, _) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -2595,8 +2595,164 @@ mod creation_tests { // He had 15, but spent 10 assert_eq!(token_balance, Some(5)); + + // There was a burn so the contract owner shouldn't have gotten more tokens + let contract_owner_token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + contract_owner_id.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He started with None, so should have None + assert_eq!(contract_owner_token_balance, None); + } + + #[test] + fn test_document_creation_paid_with_a_token_transfer() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (contract_owner_id, _, _) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); + + let (contract, gold_token_id, _) = + create_card_game_internal_token_contract_with_owner_identity_transfer_tokens( + &mut platform, + contract_owner_id.id(), + platform_version, + ); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(0)); + + assert_eq!(contract.tokens().len(), 2); + + add_tokens_to_identity(&mut platform, gold_token_id, buyer.id(), 15); + + let token_supply = platform + .drive + .fetch_token_total_supply(gold_token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(15)); + + let card_document_type = contract + .document_type_for_name("card") + .expect("expected a profile document type"); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut document = card_document_type + .random_document_with_identifier_and_entropy( + &mut rng, + buyer.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document.set("attack", 4.into()); + document.set("defense", 7.into()); + + let documents_batch_create_transition = + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + card_document_type, + entropy.0, + &key, + 2, + 0, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), + &signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition = documents_batch_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + buyer.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // The buyer had 15, but spent 10 + assert_eq!(token_balance, Some(5)); + + let contract_owner_token_balance = platform + .drive + .fetch_identity_token_balance( + gold_token_id.to_buffer(), + contract_owner_id.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He was paid 10 + assert_eq!(contract_owner_token_balance, Some(10)); } - + #[test] fn test_document_creation_paid_with_a_token_not_spending_enough() { let platform_version = PlatformVersion::latest(); @@ -2614,7 +2770,7 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, _) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -2679,7 +2835,7 @@ mod creation_tests { None, None, ) - .expect("expect to create documents batch transition"); + .expect("expect to create documents batch transition"); let documents_batch_create_serialized_transition = documents_batch_create_transition .serialize_to_bytes() @@ -2703,9 +2859,9 @@ mod creation_tests { assert_matches!( processing_result.execution_results().as_slice(), [PaidConsensusError( - ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( - _ - )), + ConsensusError::StateError( + StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError(_) + ), _ )] ); @@ -2731,7 +2887,6 @@ mod creation_tests { assert_eq!(token_balance, Some(15)); } - #[test] fn test_document_creation_paid_with_a_token_minimum_cost_set_rare_scenario() { let platform_version = PlatformVersion::latest(); @@ -2749,7 +2904,7 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, _) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -2814,7 +2969,7 @@ mod creation_tests { None, None, ) - .expect("expect to create documents batch transition"); + .expect("expect to create documents batch transition"); let documents_batch_create_serialized_transition = documents_batch_create_transition .serialize_to_bytes() @@ -2838,9 +2993,9 @@ mod creation_tests { assert_matches!( processing_result.execution_results().as_slice(), [PaidConsensusError( - ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( - _ - )), + ConsensusError::StateError( + StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError(_) + ), _ )] ); @@ -2883,7 +3038,7 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, _) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -2948,7 +3103,7 @@ mod creation_tests { None, None, ) - .expect("expect to create documents batch transition"); + .expect("expect to create documents batch transition"); let documents_batch_create_serialized_transition = documents_batch_create_transition .serialize_to_bytes() @@ -3012,7 +3167,7 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, _) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -3071,7 +3226,7 @@ mod creation_tests { None, None, ) - .expect("expect to create documents batch transition"); + .expect("expect to create documents batch transition"); let documents_batch_create_serialized_transition = documents_batch_create_transition .serialize_to_bytes() @@ -3095,9 +3250,7 @@ mod creation_tests { assert_matches!( processing_result.execution_results().as_slice(), [PaidConsensusError( - ConsensusError::StateError(StateError::RequiredTokenPaymentInfoNotSetError( - _ - )), + ConsensusError::StateError(StateError::RequiredTokenPaymentInfoNotSetError(_)), _ )] ); @@ -3140,7 +3293,7 @@ mod creation_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, _) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -3193,7 +3346,13 @@ mod creation_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, // This contract + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: None, // We'll pay whatever + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })), &signer, platform_version, None, @@ -3319,6 +3478,7 @@ mod creation_tests { contract_id: Some(token_contract.id()), token_contract_position: 0, token_amount: 5, + effect: Default::default(), gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, }) ); @@ -3410,5 +3570,25 @@ mod creation_tests { // He had 15, but spent 5 assert_eq!(token_balance, Some(10)); + + let token_supply = platform + .drive + .fetch_token_total_supply(token_id.to_buffer(), None, platform_version) + .expect("expected to fetch total supply"); + + assert_eq!(token_supply, Some(100015)); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + token_id.to_buffer(), + document_contract_owner_id.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + // He was paid 5 + assert_eq!(token_balance, Some(5)); } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs index ca5202e32ec..ed6b5edacc1 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs @@ -2,7 +2,7 @@ use super::*; mod deletion_tests { use super::*; - use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity; + use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity_burn_tokens; #[test] fn test_document_delete_on_document_type_that_is_mutable_and_can_be_deleted() { @@ -770,7 +770,7 @@ mod deletion_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, @@ -940,7 +940,7 @@ mod deletion_tests { let (buyer, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs index 86270185659..d073097768c 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/mod.rs @@ -7,4 +7,4 @@ mod transfer; use super::*; -use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity; +use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity_burn_tokens; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs index 72c5f67f096..f61445ea309 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs @@ -2849,7 +2849,7 @@ mod nft_tests { setup_identity(&mut platform, 450, dash_to_credits!(1.0)); let (contract, gold_token_id, gas_token_id) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs index d7ad6ba3d96..b08c522f2db 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs @@ -1967,7 +1967,7 @@ mod replacement_tests { let (creator, signer, key) = setup_identity(&mut platform, 234, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs index d33e544e082..a72e1bd8373 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs @@ -1045,7 +1045,7 @@ mod transfer_tests { let (receiver, _, _) = setup_identity(&mut platform, 450, dash_to_credits!(0.1)); let (contract, gold_token_id, gas_token_id) = - create_card_game_internal_token_contract_with_owner_identity( + create_card_game_internal_token_contract_with_owner_identity_burn_tokens( &mut platform, contract_owner_id.id(), platform_version, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs index a82bd7a2afb..726bb7ea680 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs @@ -33,7 +33,6 @@ use dpp::state_transition::StateTransitionLike; use drive::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionAction; use drive::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::DocumentDeleteTransitionAction; use drive::state_transition_action::batch::batched_transition::document_transition::document_replace_transition_action::DocumentReplaceTransitionAction; -use drive::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; use drive::state_transition_action::batch::BatchTransitionAction; use drive::state_transition_action::batch::v0::BatchTransitionActionV0; @@ -90,6 +89,7 @@ trait BatchTransitionInternalTransformerV0 { data_contract_id: &Identifier, owner_id: Identifier, document_transitions: &BTreeMap<&String, Vec<&DocumentTransition>>, + user_fee_increase: UserFeeIncrease, execution_context: &mut StateTransitionExecutionContext, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -103,6 +103,7 @@ trait BatchTransitionInternalTransformerV0 { document_type_name: &str, owner_id: Identifier, document_transitions: &[&DocumentTransition], + user_fee_increase: UserFeeIncrease, execution_context: &mut StateTransitionExecutionContext, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -144,6 +145,7 @@ trait BatchTransitionInternalTransformerV0 { data_contract_fetch_info: Arc, transition: &DocumentTransition, replaced_documents: &[Document], + user_fee_increase: UserFeeIncrease, owner_id: Identifier, execution_context: &mut StateTransitionExecutionContext, platform_version: &PlatformVersion, @@ -236,6 +238,7 @@ impl BatchTransitionTransformerV0 for BatchTransition { data_contract_id, owner_id, document_transitions_by_document_type, + user_fee_increase, execution_context, transaction, platform_version, @@ -350,6 +353,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { data_contract_id: &Identifier, owner_id: Identifier, document_transitions: &BTreeMap<&String, Vec<&DocumentTransition>>, + user_fee_increase: UserFeeIncrease, execution_context: &mut StateTransitionExecutionContext, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -385,6 +389,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { document_type_name, owner_id, document_transitions, + user_fee_increase, execution_context, transaction, platform_version, @@ -403,6 +408,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { document_type_name: &str, owner_id: Identifier, document_transitions: &[&DocumentTransition], + user_fee_increase: UserFeeIncrease, execution_context: &mut StateTransitionExecutionContext, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -476,6 +482,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { data_contract_fetch_info.clone(), transition, &replaced_documents, + user_fee_increase, owner_id, execution_context, platform_version, @@ -617,6 +624,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { data_contract_fetch_info: Arc, transition: &DocumentTransition, replaced_documents: &[Document], + user_fee_increase: UserFeeIncrease, owner_id: Identifier, execution_context: &mut StateTransitionExecutionContext, platform_version: &PlatformVersion, @@ -624,8 +632,8 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { match transition { DocumentTransition::Create(document_create_transition) => { let (document_create_action, fee_result) = DocumentCreateTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup( - drive, transaction, - document_create_transition, block_info, |_identifier| { + drive, owner_id, transaction, + document_create_transition, block_info, user_fee_increase, |_identifier| { Ok(data_contract_fetch_info.clone()) }, platform_version)?; @@ -706,6 +714,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { let (document_replace_action, fee_result) = DocumentReplaceTransitionAction::try_from_borrowed_document_replace_transition( document_replace_transition, + owner_id, original_document_created_at, original_document_created_at_block_height, original_document_created_at_core_block_height, @@ -713,6 +722,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { original_document_transferred_at_block_height, original_document_transferred_at_core_block_height, block_info, + user_fee_increase, |_identifier| Ok(data_contract_fetch_info.clone()), )?; @@ -726,13 +736,13 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { } } DocumentTransition::Delete(document_delete_transition) => { - let (batched_action, fee_result) = DocumentDeleteTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(document_delete_transition, |_identifier| { + let (batched_action, fee_result) = DocumentDeleteTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(document_delete_transition, owner_id, user_fee_increase, |_identifier| { Ok(data_contract_fetch_info.clone()) })?; execution_context .add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); - + Ok(batched_action) } DocumentTransition::Transfer(document_transfer_transition) => { @@ -778,8 +788,10 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { let (document_transfer_action, fee_result) = DocumentTransferTransitionAction::try_from_borrowed_document_transfer_transition( document_transfer_transition, + owner_id, original_document.clone(), //todo: remove clone block_info, + user_fee_increase, |_identifier| Ok(data_contract_fetch_info.clone()), )?; @@ -835,8 +847,10 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { let (document_update_price_action, fee_result) = DocumentUpdatePriceTransitionAction::try_from_borrowed_document_update_price_transition( document_update_price_transition, + owner_id, original_document.clone(), //todo: find a way to not have to use cloning block_info, + user_fee_increase, |_identifier| Ok(data_contract_fetch_info.clone()), )?; @@ -902,9 +916,11 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { let (document_purchase_action, fee_result) = DocumentPurchaseTransitionAction::try_from_borrowed_document_purchase_transition( document_purchase_transition, + owner_id, original_document.clone(), //todo: find a way to not have to use cloning owner_id, block_info, + user_fee_increase, |_identifier| Ok(data_contract_fetch_info.clone()), )?; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs index cb0983a8109..5f2db600793 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/advanced_structure/v0/mod.rs @@ -9,7 +9,7 @@ use dpp::consensus::basic::data_contract::{ }; use dpp::consensus::basic::BasicError; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters; -use dpp::data_contract::INITIAL_DATA_CONTRACT_VERSION; +use dpp::data_contract::{TokenContractPosition, INITIAL_DATA_CONTRACT_VERSION}; use dpp::prelude::DataContract; use dpp::state_transition::data_contract_create_transition::accessors::DataContractCreateTransitionAccessorsV0; use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; @@ -87,10 +87,10 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 } } - let expected_position = 0; - - for (token_contract_position, token_configuration) in self.data_contract().tokens() { - if expected_position != *token_contract_position { + for (expected_position, (token_contract_position, token_configuration)) in + self.data_contract().tokens().iter().enumerate() + { + if expected_position as TokenContractPosition != *token_contract_position { let bump_action = StateTransitionAction::BumpIdentityNonceAction( BumpIdentityNonceAction::from_borrowed_data_contract_create_transition(self), ); @@ -98,7 +98,7 @@ impl DataContractCreatedStateTransitionAdvancedStructureValidationV0 return Ok(ConsensusValidationResult::new_with_data_and_errors( bump_action, vec![NonContiguousContractTokenPositionsError::new( - expected_position, + expected_position as TokenContractPosition, *token_contract_position, ) .into()], diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index b411f716051..b8b2a41aa6e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -143,6 +143,7 @@ impl StateTransitionStateValidationV0 for DataContractCreateTransition { #[cfg(test)] mod tests { use crate::execution::validation::state_transition::state_transitions::tests::setup_identity; + use crate::execution::validation::state_transition::tests::create_token_contract_with_owner_identity; use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult; use crate::test::helpers::setup::TestPlatformBuilder; use assert_matches::assert_matches; @@ -151,23 +152,33 @@ mod tests { use dpp::consensus::basic::BasicError; use dpp::consensus::ConsensusError; use dpp::dash_to_credits; + use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::accessors::v1::DataContractV1Getters; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Setters; use dpp::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers; use dpp::data_contract::change_control_rules::v0::ChangeControlRulesV0; use dpp::data_contract::change_control_rules::ChangeControlRules; + use dpp::data_contract::document_type::accessors::{ + DocumentTypeV0MutGetters, DocumentTypeV1Setters, + }; use dpp::data_contract::group::v0::GroupV0; use dpp::data_contract::group::Group; use dpp::data_contract::DataContract; + use dpp::data_contract::TokenConfiguration; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dpp::identity::TimestampMillis; + use dpp::platform_value::Value; use dpp::prelude::Identifier; use dpp::serialization::PlatformSerializable; use dpp::state_transition::data_contract_create_transition::methods::DataContractCreateTransitionMethodsV0; use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; use dpp::tests::json_document::json_document_to_contract_with_ids; use dpp::tokens::calculate_token_id; + use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; + use dpp::tokens::token_amount_on_contract_token::{ + DocumentActionTokenCost, DocumentActionTokenEffect, + }; use platform_version::version::PlatformVersion; use std::collections::BTreeMap; @@ -683,6 +694,342 @@ mod tests { .expect("expected to fetch token balance"); assert_eq!(token_balance, Some(base_supply_start_amount)); } + + #[test] + fn test_data_contract_creation_with_single_token_setting_burn_of_internal_token_on_nft_purchase_should_be_allowed( + ) { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (identity, contract_signer, contract_key) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let mut data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency.json", + None, + None, + false, //no need to validate the data contracts in tests for drive + platform_version, + ) + .expect("expected to get json based contract"); + + { + let document_type = data_contract + .document_types_mut() + .get_mut("card") + .expect("expected a document type with name card"); + document_type.set_document_creation_token_cost(Some(DocumentActionTokenCost { + contract_id: None, + token_contract_position: 0, + token_amount: 5, + effect: DocumentActionTokenEffect::BurnToken, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })); + let gas_fees_paid_by_int: u8 = GasFeesPaidBy::DocumentOwner.into(); + let schema = document_type.schema_mut(); + let token_cost = schema + .get_mut("tokenCost") + .expect("expected to get token cost") + .expect("expected token cost to be set"); + let creation_token_cost = token_cost + .get_mut("create") + .expect("expected to get creation token cost") + .expect("expected creation token cost to be set"); + creation_token_cost + .set_value("tokenPosition", 0.into()) + .expect("expected to set token position"); + creation_token_cost + .set_value("amount", 5.into()) + .expect("expected to set token amount"); + creation_token_cost + .set_value( + "effect", + Value::U8(DocumentActionTokenEffect::BurnToken.into()), + ) + .expect("expected to set token pay effect"); + creation_token_cost + .set_value("gasFeesPaidBy", gas_fees_paid_by_int.into()) + .expect("expected to set token amount"); + } + + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract, + 1, + &identity.into_partial_identity_info(), + contract_key.id(), + &contract_signer, + platform_version, + None, + ) + .expect("expect to create data contract create batch transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![data_contract_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + } + + #[test] + fn test_data_contract_creation_with_single_tokensetting_transfer_on_nft_purchase_with_internal_token_should_be_allowed( + ) { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (identity, contract_signer, contract_key) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let mut data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency.json", + None, + None, + false, //no need to validate the data contracts in tests for drive + platform_version, + ) + .expect("expected to get json based contract"); + + { + let document_type = data_contract + .document_types_mut() + .get_mut("card") + .expect("expected a document type with name card"); + document_type.set_document_creation_token_cost(Some(DocumentActionTokenCost { + contract_id: None, + token_contract_position: 0, + token_amount: 5, + effect: DocumentActionTokenEffect::TransferTokenToContractOwner, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })); + let gas_fees_paid_by_int: u8 = GasFeesPaidBy::DocumentOwner.into(); + let schema = document_type.schema_mut(); + let token_cost = schema + .get_mut("tokenCost") + .expect("expected to get token cost") + .expect("expected token cost to be set"); + let creation_token_cost = token_cost + .get_mut("create") + .expect("expected to get creation token cost") + .expect("expected creation token cost to be set"); + creation_token_cost + .set_value("tokenPosition", 0.into()) + .expect("expected to set token position"); + creation_token_cost + .set_value("amount", 5.into()) + .expect("expected to set token amount"); + creation_token_cost + .set_value( + "effect", + Value::U8( + DocumentActionTokenEffect::TransferTokenToContractOwner.into(), + ), + ) + .expect("expected to set token pay effect"); + creation_token_cost + .set_value("gasFeesPaidBy", gas_fees_paid_by_int.into()) + .expect("expected to set token amount"); + } + + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract, + 1, + &identity.into_partial_identity_info(), + contract_key.id(), + &contract_signer, + platform_version, + None, + ) + .expect("expect to create data contract create batch transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![data_contract_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + } + + #[test] + fn test_data_contract_creation_with_single_token_setting_transfer_on_nft_purchase_with_external_token_should_be_allowed( + ) { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (identity, contract_signer, contract_key) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (token_contract_owner_id, _, _) = + setup_identity(&mut platform, 11, dash_to_credits!(0.1)); + + let (token_contract, _) = create_token_contract_with_owner_identity( + &mut platform, + token_contract_owner_id.id(), + None::, + None, + None, + platform_version, + ); + + let token_contract_id = token_contract.id(); + + let mut data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency.json", + None, + None, + false, //no need to validate the data contracts in tests for drive + platform_version, + ) + .expect("expected to get json based contract"); + + { + let document_type = data_contract + .document_types_mut() + .get_mut("card") + .expect("expected a document type with name card"); + document_type.set_document_creation_token_cost(Some(DocumentActionTokenCost { + contract_id: Some(token_contract_id), + token_contract_position: 0, + token_amount: 5, + effect: DocumentActionTokenEffect::TransferTokenToContractOwner, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })); + let gas_fees_paid_by_int: u8 = GasFeesPaidBy::DocumentOwner.into(); + let schema = document_type.schema_mut(); + let token_cost = schema + .get_mut("tokenCost") + .expect("expected to get token cost") + .expect("expected token cost to be set"); + let creation_token_cost = token_cost + .get_mut("create") + .expect("expected to get creation token cost") + .expect("expected creation token cost to be set"); + creation_token_cost + .set_value("contractId", token_contract_id.into()) + .expect("expected to set token contract id"); + creation_token_cost + .set_value("tokenPosition", 0.into()) + .expect("expected to set token position"); + creation_token_cost + .set_value("amount", 5.into()) + .expect("expected to set token amount"); + creation_token_cost + .set_value( + "effect", + Value::U8( + DocumentActionTokenEffect::TransferTokenToContractOwner.into(), + ), + ) + .expect("expected to set token pay effect"); + creation_token_cost + .set_value("gasFeesPaidBy", gas_fees_paid_by_int.into()) + .expect("expected to set token amount"); + } + + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract, + 1, + &identity.into_partial_identity_info(), + contract_key.id(), + &contract_signer, + platform_version, + None, + ) + .expect("expect to create data contract create batch transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![data_contract_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + } } mod pre_programmed_distribution { @@ -1188,6 +1535,133 @@ mod tests { .expect("expected to fetch token balance"); assert_eq!(token_balance, None); } + + #[test] + fn test_data_contract_creation_with_single_token_setting_burn_of_external_token_not_allowed( + ) { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (identity, contract_signer, contract_key) = + setup_identity(&mut platform, 958, dash_to_credits!(0.1)); + + let (token_contract_owner_id, _, _) = + setup_identity(&mut platform, 11, dash_to_credits!(0.1)); + + let (token_contract, _) = create_token_contract_with_owner_identity( + &mut platform, + token_contract_owner_id.id(), + None::, + None, + None, + platform_version, + ); + + let token_contract_id = token_contract.id(); + + let mut data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json", + None, + None, + false, //no need to validate the data contracts in tests for drive + platform_version, + ) + .expect("expected to get json based contract"); + + { + let document_type = data_contract + .document_types_mut() + .get_mut("card") + .expect("expected a document type with name card"); + document_type.set_document_creation_token_cost(Some(DocumentActionTokenCost { + contract_id: Some(token_contract_id), + token_contract_position: 0, + token_amount: 5, + effect: DocumentActionTokenEffect::BurnToken, + gas_fees_paid_by: GasFeesPaidBy::DocumentOwner, + })); + let gas_fees_paid_by_int: u8 = GasFeesPaidBy::DocumentOwner.into(); + let schema = document_type.schema_mut(); + let token_cost = schema + .get_mut("tokenCost") + .expect("expected to get token cost") + .expect("expected token cost to be set"); + let creation_token_cost = token_cost + .get_mut("create") + .expect("expected to get creation token cost") + .expect("expected creation token cost to be set"); + creation_token_cost + .set_value("contractId", token_contract_id.into()) + .expect("expected to set token contract id"); + creation_token_cost + .set_value("tokenPosition", 0.into()) + .expect("expected to set token position"); + creation_token_cost + .set_value("amount", 5.into()) + .expect("expected to set token amount"); + creation_token_cost + .set_value( + "effect", + Value::U8(DocumentActionTokenEffect::BurnToken.into()), + ) + .expect("expected to set token pay effect"); + creation_token_cost + .set_value("gasFeesPaidBy", gas_fees_paid_by_int.into()) + .expect("expected to set token amount"); + } + + let data_contract_create_transition = + DataContractCreateTransition::new_from_data_contract( + data_contract, + 1, + &identity.into_partial_identity_info(), + contract_key.id(), + &contract_signer, + platform_version, + None, + ) + .expect("expect to create data contract create batch transition"); + + let data_contract_create_serialized_transition = data_contract_create_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![data_contract_create_serialized_transition.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::PaidConsensusError( + ConsensusError::BasicError( + BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(_) + ), + _ + )] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + } } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 5b5d0c9b230..868de9b9e3b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -129,7 +129,7 @@ pub(in crate::execution) mod tests { use dpp::data_contract::associated_token::token_configuration::TokenConfiguration; use dpp::data_contract::group::Group; use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; - use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenCost; + use dpp::tokens::token_amount_on_contract_token::{DocumentActionTokenCost, DocumentActionTokenEffect}; use dpp::data_contract::document_type::accessors::DocumentTypeV0MutGetters; /// We add an identity, but we also add the same amount to system credits @@ -2372,7 +2372,34 @@ pub(in crate::execution) mod tests { (basic_token_contract, token_id.into()) } - pub(in crate::execution) fn create_card_game_internal_token_contract_with_owner_identity( + pub(in crate::execution) fn create_card_game_internal_token_contract_with_owner_identity_burn_tokens( + platform: &mut TempPlatform, + identity_id: Identifier, + platform_version: &PlatformVersion, + ) -> (DataContract, Identifier, Identifier) { + let data_contract_id = DataContract::generate_data_contract_id_v0(identity_id, 1); + + let basic_token_contract = setup_contract( + &platform.drive, + "tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency-burn-tokens.json", + Some(data_contract_id.to_buffer()), + Some(identity_id.to_buffer()), + Some(|data_contract: &mut DataContract| { + data_contract.set_created_at_epoch(Some(0)); + data_contract.set_created_at(Some(0)); + data_contract.set_created_at_block_height(Some(0)); + }), + None, + Some(platform_version), + ); + + let token_id = calculate_token_id(data_contract_id.as_bytes(), 0); + let token_id_2 = calculate_token_id(data_contract_id.as_bytes(), 1); + + (basic_token_contract, token_id.into(), token_id_2.into()) + } + + pub(in crate::execution) fn create_card_game_internal_token_contract_with_owner_identity_transfer_tokens( platform: &mut TempPlatform, identity_id: Identifier, platform_version: &PlatformVersion, @@ -2424,6 +2451,7 @@ pub(in crate::execution) mod tests { contract_id: Some(token_contract_id), token_contract_position, token_amount: token_cost_amount, + effect: DocumentActionTokenEffect::TransferTokenToContractOwner, gas_fees_paid_by, })); let gas_fees_paid_by_int: u8 = gas_fees_paid_by.into(); diff --git a/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency-burn-tokens.json b/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency-burn-tokens.json new file mode 100644 index 00000000000..719d2b6e352 --- /dev/null +++ b/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-in-game-currency-burn-tokens.json @@ -0,0 +1,178 @@ +{ + "$format_version": "1", + "id": "86LHvdC1Tqx5P97LQUSibGFqf2vnKFpB6VkqQ7oso86e", + "ownerId": "2QjL594djCH2NyDsn45vd6yQjEDHupMKo7CEGVTHtQxU", + "version": 1, + "documentSchemas": { + "card": { + "type": "object", + "documentsMutable": true, + "canBeDeleted": true, + "transferable": 1, + "tradeMode": 1, + "tokenCost": { + "create": { "tokenPosition": 0, "amount": 10, + "effect": 1 + }, + "delete": { "tokenPosition": 1, "amount": 1, "effect": 1 }, + "replace": { "tokenPosition": 1, "amount": 2, "effect": 1 }, + "transfer": { "tokenPosition": 1, "amount": 1, "effect": 1 }, + "update_price": { "tokenPosition": 1, "amount": 1, "effect": 1 }, + "purchase": { "tokenPosition": 0, "amount": 3, "effect": 1 } + }, + "properties": { + "name": { + "type": "string", + "description": "Name of the card", + "maxLength": 63, + "position": 0 + }, + "description": { + "type": "string", + "description": "Description of the card", + "maxLength": 256, + "position": 1 + }, + "imageUrl": { + "type": "string", + "description": "URL of the image associated with the card", + "maxLength": 2048, + "format": "uri", + "position": 2 + }, + "imageHash": { + "type": "array", + "description": "SHA256 hash of the bytes of the image specified by imageUrl", + "byteArray": true, + "minItems": 32, + "maxItems": 32, + "position": 3 + }, + "imageFingerprint": { + "type": "array", + "description": "dHash of the image specified by imageUrl", + "byteArray": true, + "minItems": 8, + "maxItems": 8, + "position": 4 + }, + "attack": { + "type": "integer", + "description": "Attack power of the card", + "minimum": 0, + "position": 5 + }, + "defense": { + "type": "integer", + "description": "Defense level of the card", + "minimum": 0, + "position": 6 + } + }, + "indices": [ + { + "name": "owner", + "properties": [ + { + "$ownerId": "asc" + } + ] + }, + { + "name": "attack", + "properties": [ + { + "attack": "asc" + } + ] + }, + { + "name": "defense", + "properties": [ + { + "defense": "asc" + } + ] + }, + { + "name": "transferredAt", + "properties": [ + { + "$transferredAt": "asc" + } + ] + }, + { + "name": "ownerTransferredAt", + "properties": [ + { + "$ownerId": "asc" + }, + { + "$transferredAt": "asc" + } + ] + }, + { + "name": "transferredAtBlockHeight", + "properties": [ + { + "$transferredAtBlockHeight": "asc" + } + ] + }, + { + "name": "transferredAtCoreBlockHeight", + "properties": [ + { + "$transferredAtCoreBlockHeight": "asc" + } + ] + } + ], + "required": [ + "name", + "$transferredAt", + "$transferredAtBlockHeight", + "$transferredAtCoreBlockHeight", + "attack", + "defense" + ], + "additionalProperties": false + } + }, + "tokens": { + "0": { + "$format_version": "0", + "conventions": { + "$format_version": "0", + "localizations": { + "en": { + "$format_version": "0", + "shouldCapitalize": true, + "pluralForm": "gold", + "singularForm": "gold" + } + }, + "decimals": 0 + }, + "maxSupply": null + }, + "1": { + "$format_version": "0", + "conventions": { + "$format_version": "0", + "localizations": { + "en": { + "$format_version": "0", + "shouldCapitalize": true, + "pluralForm": "gas", + "singularForm": "gas" + } + }, + "decimals": 0 + }, + "maxSupply": null + } + } +} \ No newline at end of file diff --git a/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json b/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json index 4311665298e..f12d9dc73da 100644 --- a/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json +++ b/packages/rs-drive-abci/tests/supporting_files/contract/crypto-card-game/crypto-card-game-use-external-currency.json @@ -11,7 +11,7 @@ "transferable": 1, "tradeMode": 1, "tokenCost": { - "create": { "contractId": "86LHvdC1Tqx5P97LQUSibGFqf2vnKFpB6VkqQ7oso86e", "tokenPosition": 0, "amount": 10, "gasFeesPaidBy": 1 } + "create": { "contractId": "86LHvdC1Tqx5P97LQUSibGFqf2vnKFpB6VkqQ7oso86e", "tokenPosition": 0, "amount": 10, "effect": 0, "gasFeesPaidBy": 1 } }, "properties": { "name": { diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_create_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_create_transition.rs index 92e4364028c..d3807a5ea2c 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_create_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_create_transition.rs @@ -12,6 +12,8 @@ use dpp::block::epoch::Epoch; use dpp::document::Document; use dpp::prelude::Identifier; use std::borrow::Cow; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::{DocumentCreateTransitionAction, DocumentCreateTransitionActionAccessorsV0, DocumentFromCreateTransitionAction}; use dpp::version::PlatformVersion; @@ -65,12 +67,24 @@ impl DriveHighLevelBatchOperationConverter for DocumentCreateTransitionAction { }, )]; - if let Some((token_id, cost)) = document_creation_token_cost { - ops.push(TokenOperation(TokenOperationType::TokenBurn { - token_id, - identity_balance_holder_id: owner_id, - burn_amount: cost, - })); + if let Some((token_id, effect, cost)) = document_creation_token_cost { + match effect { + DocumentActionTokenEffect::TransferTokenToContractOwner => { + ops.push(TokenOperation(TokenOperationType::TokenTransfer { + token_id, + sender_id: owner_id, + recipient_id: contract_fetch_info.contract.owner_id(), + amount: cost, + })); + } + DocumentActionTokenEffect::BurnToken => { + ops.push(TokenOperation(TokenOperationType::TokenBurn { + token_id, + identity_balance_holder_id: owner_id, + burn_amount: cost, + })); + } + } } if let Some((contested_document_resource_vote_poll, credits)) = diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_delete_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_delete_transition.rs index d82f1af2e17..3a2df2af44f 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_delete_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_delete_transition.rs @@ -5,7 +5,9 @@ use crate::util::batch::{DocumentOperationType, DriveOperation, IdentityOperatio use crate::error::Error; use dpp::block::epoch::Epoch; +use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::identifier::Identifier; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::DocumentDeleteTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::v0::DocumentDeleteTransitionActionAccessorsV0; @@ -31,6 +33,8 @@ impl DriveHighLevelBatchOperationConverter for DocumentDeleteTransitionAction { 0 => { let base = self.base_owned(); + let contract_fetch_info = base.data_contract_fetch_info(); + let data_contract_id = base.data_contract_id(); let identity_contract_nonce = base.identity_contract_nonce(); @@ -54,12 +58,24 @@ impl DriveHighLevelBatchOperationConverter for DocumentDeleteTransitionAction { }), ]; - if let Some((token_id, cost)) = document_deletion_token_cost { - ops.push(TokenOperation(TokenOperationType::TokenBurn { - token_id, - identity_balance_holder_id: owner_id, - burn_amount: cost, - })); + if let Some((token_id, effect, cost)) = document_deletion_token_cost { + match effect { + DocumentActionTokenEffect::TransferTokenToContractOwner => { + ops.push(TokenOperation(TokenOperationType::TokenTransfer { + token_id, + sender_id: owner_id, + recipient_id: contract_fetch_info.contract.owner_id(), + amount: cost, + })); + } + DocumentActionTokenEffect::BurnToken => { + ops.push(TokenOperation(TokenOperationType::TokenBurn { + token_id, + identity_balance_holder_id: owner_id, + burn_amount: cost, + })); + } + } } Ok(ops) diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_purchase_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_purchase_transition.rs index 15af66ab529..b2fe6465f30 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_purchase_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_purchase_transition.rs @@ -9,6 +9,8 @@ use dpp::block::epoch::Epoch; use dpp::prelude::Identifier; use std::borrow::Cow; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_purchase_transition_action::{DocumentPurchaseTransitionAction, DocumentPurchaseTransitionActionAccessorsV0}; use dpp::version::PlatformVersion; @@ -37,6 +39,8 @@ impl DriveHighLevelBatchOperationConverter for DocumentPurchaseTransitionAction let purchase_amount = self.price(); let contract_fetch_info = self.base().data_contract_fetch_info(); + let contract_owner_id = contract_fetch_info.contract.owner_id(); + let document_purchase_token_cost = self.base().token_cost(); let document = self.document_owned(); @@ -77,12 +81,24 @@ impl DriveHighLevelBatchOperationConverter for DocumentPurchaseTransitionAction }), ]; - if let Some((token_id, cost)) = document_purchase_token_cost { - ops.push(TokenOperation(TokenOperationType::TokenBurn { - token_id, - identity_balance_holder_id: owner_id, - burn_amount: cost, - })); + if let Some((token_id, effect, cost)) = document_purchase_token_cost { + match effect { + DocumentActionTokenEffect::TransferTokenToContractOwner => { + ops.push(TokenOperation(TokenOperationType::TokenTransfer { + token_id, + sender_id: owner_id, + recipient_id: contract_owner_id, + amount: cost, + })); + } + DocumentActionTokenEffect::BurnToken => { + ops.push(TokenOperation(TokenOperationType::TokenBurn { + token_id, + identity_balance_holder_id: owner_id, + burn_amount: cost, + })); + } + } } Ok(ops) diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_replace_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_replace_transition.rs index 18f7efe15ae..c967f532204 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_replace_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_replace_transition.rs @@ -10,6 +10,8 @@ use dpp::block::epoch::Epoch; use dpp::document::Document; use dpp::prelude::Identifier; use std::borrow::Cow; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_replace_transition_action::{DocumentFromReplaceTransitionAction, DocumentReplaceTransitionAction, DocumentReplaceTransitionActionAccessorsV0}; use dpp::version::PlatformVersion; @@ -35,6 +37,8 @@ impl DriveHighLevelBatchOperationConverter for DocumentReplaceTransitionAction { let document_type_name = self.base().document_type_name().clone(); let identity_contract_nonce = self.base().identity_contract_nonce(); let contract_fetch_info = self.base().data_contract_fetch_info(); + let contract_owner_id = contract_fetch_info.contract.owner_id(); + let document_replacement_token_cost = self.base().token_cost(); let document = Document::try_from_owned_replace_transition_action( self, @@ -64,12 +68,24 @@ impl DriveHighLevelBatchOperationConverter for DocumentReplaceTransitionAction { }), ]; - if let Some((token_id, cost)) = document_replacement_token_cost { - ops.push(TokenOperation(TokenOperationType::TokenBurn { - token_id, - identity_balance_holder_id: owner_id, - burn_amount: cost, - })); + if let Some((token_id, effect, cost)) = document_replacement_token_cost { + match effect { + DocumentActionTokenEffect::TransferTokenToContractOwner => { + ops.push(TokenOperation(TokenOperationType::TokenTransfer { + token_id, + sender_id: owner_id, + recipient_id: contract_owner_id, + amount: cost, + })); + } + DocumentActionTokenEffect::BurnToken => { + ops.push(TokenOperation(TokenOperationType::TokenBurn { + token_id, + identity_balance_holder_id: owner_id, + burn_amount: cost, + })); + } + } } Ok(ops) diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_transfer_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_transfer_transition.rs index 55e0dec6117..8239e71d232 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_transfer_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_transfer_transition.rs @@ -10,6 +10,8 @@ use dpp::block::epoch::Epoch; use dpp::document::DocumentV0Getters; use dpp::prelude::Identifier; use std::borrow::Cow; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_transfer_transition_action::{DocumentTransferTransitionAction, DocumentTransferTransitionActionAccessorsV0}; use dpp::version::PlatformVersion; @@ -35,6 +37,8 @@ impl DriveHighLevelBatchOperationConverter for DocumentTransferTransitionAction let document_type_name = self.base().document_type_name().clone(); let identity_contract_nonce = self.base().identity_contract_nonce(); let contract_fetch_info = self.base().data_contract_fetch_info(); + let contract_owner_id = contract_fetch_info.contract.owner_id(); + let document_transfer_token_cost = self.base().token_cost(); let document = self.document_owned(); @@ -66,12 +70,24 @@ impl DriveHighLevelBatchOperationConverter for DocumentTransferTransitionAction }), ]; - if let Some((token_id, cost)) = document_transfer_token_cost { - ops.push(TokenOperation(TokenOperationType::TokenBurn { - token_id, - identity_balance_holder_id: owner_id, - burn_amount: cost, - })); + if let Some((token_id, effect, cost)) = document_transfer_token_cost { + match effect { + DocumentActionTokenEffect::TransferTokenToContractOwner => { + ops.push(TokenOperation(TokenOperationType::TokenTransfer { + token_id, + sender_id: owner_id, + recipient_id: contract_owner_id, + amount: cost, + })); + } + DocumentActionTokenEffect::BurnToken => { + ops.push(TokenOperation(TokenOperationType::TokenBurn { + token_id, + identity_balance_holder_id: owner_id, + burn_amount: cost, + })); + } + } } Ok(ops) diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs index b3d08472c1a..44b74ac809d 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs @@ -9,6 +9,8 @@ use dpp::block::epoch::Epoch; use dpp::prelude::Identifier; use std::borrow::Cow; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_update_price_transition_action::{DocumentUpdatePriceTransitionAction, DocumentUpdatePriceTransitionActionAccessorsV0}; use dpp::version::PlatformVersion; @@ -35,6 +37,8 @@ impl DriveHighLevelBatchOperationConverter for DocumentUpdatePriceTransitionActi let identity_contract_nonce = self.base().identity_contract_nonce(); let fetch_info = self.base().data_contract_fetch_info(); let document_update_price_token_cost = self.base().token_cost(); + let contract_owner_id = fetch_info.contract.owner_id(); + let document = self.document_owned(); let storage_flags = @@ -59,12 +63,24 @@ impl DriveHighLevelBatchOperationConverter for DocumentUpdatePriceTransitionActi }), ]; - if let Some((token_id, cost)) = document_update_price_token_cost { - ops.push(TokenOperation(TokenOperationType::TokenBurn { - token_id, - identity_balance_holder_id: owner_id, - burn_amount: cost, - })); + if let Some((token_id, effect, cost)) = document_update_price_token_cost { + match effect { + DocumentActionTokenEffect::TransferTokenToContractOwner => { + ops.push(TokenOperation(TokenOperationType::TokenTransfer { + token_id, + sender_id: owner_id, + recipient_id: contract_owner_id, + amount: cost, + })); + } + DocumentActionTokenEffect::BurnToken => { + ops.push(TokenOperation(TokenOperationType::TokenBurn { + token_id, + identity_balance_holder_id: owner_id, + burn_amount: cost, + })); + } + } } Ok(ops) diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/mod.rs index 3aa64620368..9ed7cb26286 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/mod.rs @@ -6,6 +6,7 @@ use dpp::balances::credits::TokenAmount; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::data_contract::document_type::DocumentTypeRef; use dpp::prelude::IdentityNonce; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use dpp::ProtocolError; use std::sync::Arc; @@ -77,7 +78,7 @@ impl DocumentBaseTransitionActionAccessorsV0 for DocumentBaseTransitionAction { } } - fn token_cost(&self) -> Option<(Identifier, TokenAmount)> { + fn token_cost(&self) -> Option<(Identifier, DocumentActionTokenEffect, TokenAmount)> { match self { DocumentBaseTransitionAction::V0(v0) => v0.token_cost, } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs index 3ab4c93d9ab..84fb5fcf744 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/transformer.rs @@ -10,24 +10,6 @@ use crate::error::Error; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionV0}; impl DocumentBaseTransitionAction { - /// from base transition with contract lookup - pub fn try_from_base_transition_with_contract_lookup( - value: DocumentBaseTransition, - get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - get_token_cost: impl Fn(&DocumentType) -> Option, - action: &str, - ) -> Result, Error> { - Ok( - DocumentBaseTransitionActionV0::try_from_base_transition_with_contract_lookup( - value, - get_data_contract, - get_token_cost, - action, - )? - .map(|v0| v0.into()), - ) - } - /// from borrowed base transition with contract lookup pub fn try_from_borrowed_base_transition_with_contract_lookup( value: &DocumentBaseTransition, @@ -42,7 +24,7 @@ impl DocumentBaseTransitionAction { get_token_cost, action, )? - .map(|v0| v0.into()), + .map(|v0| v0.into()), ) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs index 71a9e01f479..4d7a8327015 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/mod.rs @@ -7,6 +7,7 @@ use dpp::data_contract::document_type::DocumentTypeRef; use dpp::identifier::Identifier; use dpp::prelude::IdentityNonce; use dpp::tokens::gas_fees_paid_by::GasFeesPaidBy; +use dpp::tokens::token_amount_on_contract_token::DocumentActionTokenEffect; use dpp::ProtocolError; use std::sync::Arc; @@ -22,7 +23,7 @@ pub struct DocumentBaseTransitionActionV0 { /// A potential data contract pub data_contract: Arc, /// Token cost with the token_id coming first - pub token_cost: Option<(Identifier, TokenAmount)>, + pub token_cost: Option<(Identifier, DocumentActionTokenEffect, TokenAmount)>, /// Who pays the gas fees pub gas_fees_paid_by: GasFeesPaidBy, } @@ -53,5 +54,5 @@ pub trait DocumentBaseTransitionActionAccessorsV0 { fn identity_contract_nonce(&self) -> IdentityNonce; /// Token cost - fn token_cost(&self) -> Option<(Identifier, TokenAmount)>; + fn token_cost(&self) -> Option<(Identifier, DocumentActionTokenEffect, TokenAmount)>; } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs index 21215cb2b1e..a4bbfc86333 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_base_transition_action/v0/transformer.rs @@ -20,92 +20,6 @@ use crate::error::Error; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionV0; impl DocumentBaseTransitionActionV0 { - /// try from base transition with contract lookup - pub fn try_from_base_transition_with_contract_lookup( - value: DocumentBaseTransition, - get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - get_token_cost: impl Fn(&DocumentType) -> Option, - action: &str, - ) -> Result, Error> { - let data_contract_id = value.data_contract_id(); - let data_contract = get_data_contract(data_contract_id)?; - let document_type = data_contract - .contract - .document_type_borrowed_for_name(value.document_type_name().as_str())?; - let document_action_token_cost = get_token_cost(document_type); - let token_cost = document_action_token_cost.map( - |DocumentActionTokenCost { - contract_id, - token_contract_position, - token_amount, - .. - }| { - ( - calculate_token_id( - contract_id.unwrap_or(data_contract_id).as_bytes(), - token_contract_position, - ) - .into(), - token_amount, - ) - }, - ); - if let Some(document_action_token_cost) = document_action_token_cost { - let Some(token_payment_info) = value.token_payment_info_ref() else { - return Ok(ConsensusValidationResult::new_with_error( - ConsensusError::StateError(StateError::RequiredTokenPaymentInfoNotSetError( - RequiredTokenPaymentInfoNotSetError::new( - token_cost.expect("expected token cost").0, - action.to_string(), - ), - )), - )); - }; - // Let's see that the user agreed to pay using the correct token - if !token_payment_info.matches_token_contract(&document_action_token_cost.contract_id, document_action_token_cost.token_contract_position) { - return Ok(ConsensusValidationResult::new_with_error( - ConsensusError::StateError(StateError::IdentityTryingToPayWithWrongTokenError( - IdentityTryingToPayWithWrongTokenError::new( - document_action_token_cost.contract_id, - document_action_token_cost.token_contract_position, - token_cost.expect("expected token cost").0, - token_payment_info.payment_token_contract_id(), - token_payment_info.token_contract_position(), - token_payment_info.token_id(data_contract_id) - ), - )), - )); - } - // Let's see that the user agreed to pay the required amount - if !token_payment_info.is_valid_for_required_cost(document_action_token_cost.token_amount) { - return Ok(ConsensusValidationResult::new_with_error( - ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( - IdentityHasNotAgreedToPayRequiredTokenAmountError::new( - token_cost.expect("expected token cost").0, - document_action_token_cost.token_amount, - token_payment_info.minimum_token_cost(), - token_payment_info.maximum_token_cost(), - action.to_string(), - ), - )), - )); - } - } - let gas_fees_paid_by = value - .token_payment_info_ref() - .as_ref() - .map(|token_payment_info| token_payment_info.gas_fees_paid_by()) - .unwrap_or(GasFeesPaidBy::DocumentOwner); - Ok(DocumentBaseTransitionActionV0 { - id: value.id(), - identity_contract_nonce: value.identity_contract_nonce(), - document_type_name: value.document_type_name_owned(), - data_contract, - token_cost, - gas_fees_paid_by, - }.into()) - } - /// try from borrowed base transition with contract lookup pub fn try_from_borrowed_base_transition_with_contract_lookup( value: &DocumentBaseTransition, @@ -124,6 +38,7 @@ impl DocumentBaseTransitionActionV0 { contract_id, token_contract_position, token_amount, + effect, .. }| { ( @@ -131,7 +46,8 @@ impl DocumentBaseTransitionActionV0 { contract_id.unwrap_or(data_contract_id).as_bytes(), token_contract_position, ) - .into(), + .into(), + effect, token_amount, ) }, @@ -148,7 +64,10 @@ impl DocumentBaseTransitionActionV0 { )); }; // Let's see that the user agreed to pay using the correct token - if !token_payment_info.matches_token_contract(&document_action_token_cost.contract_id, document_action_token_cost.token_contract_position) { + if !token_payment_info.matches_token_contract( + &document_action_token_cost.contract_id, + document_action_token_cost.token_contract_position, + ) { return Ok(ConsensusValidationResult::new_with_error( ConsensusError::StateError(StateError::IdentityTryingToPayWithWrongTokenError( IdentityTryingToPayWithWrongTokenError::new( @@ -157,23 +76,27 @@ impl DocumentBaseTransitionActionV0 { token_cost.expect("expected token cost").0, token_payment_info.payment_token_contract_id(), token_payment_info.token_contract_position(), - token_payment_info.token_id(data_contract_id) + token_payment_info.token_id(data_contract_id), ), )), )); } // Let's see that the user agreed to pay the required amount - if !token_payment_info.is_valid_for_required_cost(document_action_token_cost.token_amount) { + if !token_payment_info + .is_valid_for_required_cost(document_action_token_cost.token_amount) + { return Ok(ConsensusValidationResult::new_with_error( - ConsensusError::StateError(StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( - IdentityHasNotAgreedToPayRequiredTokenAmountError::new( - token_cost.expect("expected token cost").0, - document_action_token_cost.token_amount, - token_payment_info.minimum_token_cost(), - token_payment_info.maximum_token_cost(), - action.to_string(), + ConsensusError::StateError( + StateError::IdentityHasNotAgreedToPayRequiredTokenAmountError( + IdentityHasNotAgreedToPayRequiredTokenAmountError::new( + token_cost.expect("expected token cost").0, + document_action_token_cost.token_amount, + token_payment_info.minimum_token_cost(), + token_payment_info.maximum_token_cost(), + action.to_string(), + ), ), - )), + ), )); } } @@ -189,6 +112,7 @@ impl DocumentBaseTransitionActionV0 { data_contract, token_cost, gas_fees_paid_by, - }.into()) + } + .into()) } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs index d85ef310c9e..34e3164787c 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs @@ -14,30 +14,6 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::{DocumentCreateTransitionAction, DocumentCreateTransitionActionV0}; impl DocumentCreateTransitionAction { - /// from_document_create_transition_with_contract_lookup - pub fn try_from_document_create_transition_with_contract_lookup( - drive: &Drive, - owner_id: Identifier, - transaction: TransactionArg, - value: DocumentCreateTransition, - block_info: &BlockInfo, - user_fee_increase: UserFeeIncrease, - get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - platform_version: &PlatformVersion, - ) -> Result< - ( - ConsensusValidationResult, - FeeResult, - ), - Error, - > { - match value { - DocumentCreateTransition::V0(v0) => { - DocumentCreateTransitionActionV0::try_from_document_create_transition_with_contract_lookup(drive, owner_id, transaction, v0, block_info, user_fee_increase, get_data_contract, platform_version) - } - } - } - /// from_document_borrowed_create_transition_with_contract_lookup pub fn try_from_document_borrowed_create_transition_with_contract_lookup( drive: &Drive, diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs index 98fbc0c51bc..cb89a46b4d4 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs @@ -22,17 +22,17 @@ use crate::state_transition_action::batch::batched_transition::document_transiti use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentCreateTransitionActionV0 { - /// try from document create transition with contract lookup - pub fn try_from_document_create_transition_with_contract_lookup( + /// try from borrowed document create transition with contract lookup + pub fn try_from_borrowed_document_create_transition_with_contract_lookup( drive: &Drive, owner_id: Identifier, transaction: TransactionArg, - value: DocumentCreateTransitionV0, + value: &DocumentCreateTransitionV0, block_info: &BlockInfo, user_fee_increase: UserFeeIncrease, get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, platform_version: &PlatformVersion, - ) -> Result< + ) -> Result< ( ConsensusValidationResult, FeeResult, @@ -45,18 +45,19 @@ impl DocumentCreateTransitionActionV0 { prefunded_voting_balance, .. } = value; - let base_action_validation_result = DocumentBaseTransitionAction::try_from_base_transition_with_contract_lookup( - base, - get_data_contract, - |document_type| document_type.document_creation_token_cost(), - "create", - )?; + let base_action_validation_result = + DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( + base, + get_data_contract, + |document_type| document_type.document_creation_token_cost(), + "create", + )?; let base = match base_action_validation_result.is_valid() { true => base_action_validation_result.into_data()?, false => { let bump_action = - BumpIdentityDataContractNonceAction::from_document_base_transition( + BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition( base, owner_id, user_fee_increase, @@ -78,113 +79,6 @@ impl DocumentCreateTransitionActionV0 { let document_type_indexes = document_type.indexes(); - let prefunded_voting_balances_by_vote_poll = prefunded_voting_balance - .map(|(index_name, credits)| { - let index = document_type_indexes.get(&index_name).ok_or( - ProtocolError::UnknownContestedIndexResolution(format!( - "index {} not found on document type {}", - index_name.clone(), - document_type.name() - )), - )?; - let index_values = index.extract_values(&data); - - let vote_poll = ContestedDocumentResourceVotePoll { - contract_id: base.data_contract_id(), - document_type_name: base.document_type_name().clone(), - index_name, - index_values, - }; - - let resolved_vote_poll = vote_poll - .resolve_owned_with_provided_arc_contract_fetch_info( - base.data_contract_fetch_info(), - )?; - - Ok::<_, Error>((resolved_vote_poll, credits)) - }) - .transpose()?; - - let mut fee_result = FeeResult::default(); - - let (current_store_contest_info, should_store_contest_info) = - if let Some((contested_document_resource_vote_poll, _)) = - &prefunded_voting_balances_by_vote_poll - { - let (fetch_fee_result, maybe_current_store_contest_info) = drive - .fetch_contested_document_vote_poll_stored_info( - contested_document_resource_vote_poll, - Some(&block_info.epoch), - transaction, - platform_version, - )?; - - fee_result = fetch_fee_result.ok_or(Error::Drive( - DriveError::CorruptedCodeExecution("expected fee result"), - ))?; - let should_store_contest_info = if maybe_current_store_contest_info.is_none() { - // We are starting a new contest - Some(ContestedDocumentVotePollStoredInfo::new( - *block_info, - platform_version, - )?) - } else { - None - }; - (maybe_current_store_contest_info, should_store_contest_info) - } else { - (None, None) - }; - - Ok(( - BatchedTransitionAction::DocumentAction(DocumentTransitionAction::CreateAction( - DocumentCreateTransitionActionV0 { - base, - block_info: *block_info, - data, - prefunded_voting_balance: prefunded_voting_balances_by_vote_poll, - current_store_contest_info, - should_store_contest_info, - } - .into(), - )) - .into(), - fee_result, - )) - } - - /// try from borrowed document create transition with contract lookup - pub fn try_from_borrowed_document_create_transition_with_contract_lookup( - drive: &Drive, - transaction: TransactionArg, - value: &DocumentCreateTransitionV0, - block_info: &BlockInfo, - get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - platform_version: &PlatformVersion, - ) -> Result< - ( - ConsensusValidationResult, - FeeResult, - ), - Error, - > { - let DocumentCreateTransitionV0 { - base, - data, - prefunded_voting_balance, - .. - } = value; - let base = - DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( - base, - get_data_contract, - |document_type| document_type.document_creation_token_cost(), - )?; - - let document_type = base.document_type()?; - - let document_type_indexes = document_type.indexes(); - let prefunded_voting_balances_by_vote_poll = prefunded_voting_balance .as_ref() .map(|(index_name, credits)| { @@ -254,9 +148,9 @@ impl DocumentCreateTransitionActionV0 { current_store_contest_info, should_store_contest_info, } - .into(), - )) .into(), + )) + .into(), fee_result, )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs index 4b26aea2be5..d5659d0a203 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs @@ -10,24 +10,6 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::{DocumentDeleteTransitionAction, DocumentDeleteTransitionActionV0}; impl DocumentDeleteTransitionAction { - /// from - pub fn try_from_document_create_transition_with_contract_lookup( - value: DocumentDeleteTransition, - owner_id: Identifier, - user_fee_increase: UserFeeIncrease, - get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result< - ( - ConsensusValidationResult, - FeeResult, - ), - Error, - > { - match value { - DocumentDeleteTransition::V0(v0) => DocumentDeleteTransitionActionV0::try_from_document_delete_transition_with_contract_lookup(v0, owner_id, user_fee_increase, get_data_contract), - } - } - /// from borrowed pub fn try_from_document_borrowed_create_transition_with_contract_lookup( value: &DocumentDeleteTransition, diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs index 0de569ed9c4..82129c18b20 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs @@ -11,40 +11,9 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionAction; use crate::state_transition_action::batch::batched_transition::document_transition::document_delete_transition_action::v0::DocumentDeleteTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentDeleteTransitionActionV0 { - /// try from - pub fn try_from_document_delete_transition_with_contract_lookup( - value: DocumentDeleteTransitionV0, - owner_id: Identifier, - user_fee_increase: UserFeeIncrease, - get_data_contract: impl Fn(Identifier) -> Result, ProtocolError>, - ) -> Result< - ( - ConsensusValidationResult, - FeeResult, - ), - Error, - > { - let DocumentDeleteTransitionV0 { base, .. } = value; - - Ok(( - BatchedTransitionAction::DocumentAction(DocumentTransitionAction::DeleteAction( - DocumentDeleteTransitionActionV0 { - base: DocumentBaseTransitionAction::try_from_base_transition_with_contract_lookup( - base, - get_data_contract, - |document_type| document_type.document_deletion_token_cost(), - )? - } - - .into(), - )) - .into(), - FeeResult::default(), - )) - } - /// try from borrowed pub fn try_from_borrowed_document_delete_transition_with_contract_lookup( value: &DocumentDeleteTransitionV0, @@ -59,19 +28,42 @@ impl DocumentDeleteTransitionActionV0 { Error, > { let DocumentDeleteTransitionV0 { base, .. } = value; - Ok(( - BatchedTransitionAction::DocumentAction(DocumentTransitionAction::DeleteAction( - DocumentDeleteTransitionActionV0 { - base: DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( + + let base_action_validation_result = + DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( + base, + get_data_contract, + |document_type| document_type.document_creation_token_cost(), + "delete", + )?; + + let base = match base_action_validation_result.is_valid() { + true => base_action_validation_result.into_data()?, + false => { + let bump_action = + BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition( base, - get_data_contract, - |document_type| document_type.document_deletion_token_cost(), - )? - } + owner_id, + user_fee_increase, + ); + let batched_action = + BatchedTransitionAction::BumpIdentityDataContractNonce(bump_action); - .into(), + return Ok(( + ConsensusValidationResult::new_with_data_and_errors( + batched_action, + base_action_validation_result.errors, + ), + FeeResult::default(), + )); + } + }; + + Ok(( + BatchedTransitionAction::DocumentAction(DocumentTransitionAction::DeleteAction( + DocumentDeleteTransitionActionV0 { base }.into(), )) - .into(), + .into(), FeeResult::default(), )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs index bf54d862048..d6082362fc6 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/transformer.rs @@ -29,7 +29,7 @@ impl DocumentPurchaseTransitionAction { Error, > { match document_purchase_transition { - DocumentPurchaseTransition::V0(v0) => + DocumentPurchaseTransition::V0(v0) => { DocumentPurchaseTransitionActionV0::try_from_borrowed_document_purchase_transition( v0, owner_id, @@ -38,7 +38,8 @@ impl DocumentPurchaseTransitionAction { block_info, user_fee_increase, get_data_contract, - ), + ) + } } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs index 17cc8452f79..208a3ea2f36 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs @@ -14,6 +14,7 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_purchase_transition_action::v0::DocumentPurchaseTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentPurchaseTransitionActionV0 { /// try from borrowed @@ -33,13 +34,35 @@ impl DocumentPurchaseTransitionActionV0 { Error, > { let DocumentPurchaseTransitionV0 { base, price, .. } = document_purchase_transition; - let base = + let base_action_validation_result = DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_purchase_token_cost(), + |document_type| document_type.document_creation_token_cost(), + "purchase", )?; + let base = match base_action_validation_result.is_valid() { + true => base_action_validation_result.into_data()?, + false => { + let bump_action = + BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition( + base, + owner_id, + user_fee_increase, + ); + let batched_action = + BatchedTransitionAction::BumpIdentityDataContractNonce(bump_action); + + return Ok(( + ConsensusValidationResult::new_with_data_and_errors( + batched_action, + base_action_validation_result.errors, + ), + FeeResult::default(), + )); + } + }; let original_owner_id = original_document.owner_id(); let mut modified_document = original_document; @@ -71,9 +94,9 @@ impl DocumentPurchaseTransitionActionV0 { original_owner_id, price: *price, } - .into(), - )) .into(), + )) + .into(), FeeResult::default(), )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs index 79093e0c7ee..7cd6cfb39bc 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/transformer.rs @@ -34,7 +34,7 @@ impl DocumentReplaceTransitionAction { Error, > { match document_replace_transition { - DocumentReplaceTransition::V0(v0) => + DocumentReplaceTransition::V0(v0) => { DocumentReplaceTransitionActionV0::try_from_borrowed_document_replace_transition( v0, owner_id, @@ -47,7 +47,8 @@ impl DocumentReplaceTransitionAction { block_info, user_fee_increase, get_data_contract, - ), + ) + } } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs index da191ff47ac..367974151d9 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs @@ -14,6 +14,7 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_replace_transition_action::v0::DocumentReplaceTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentReplaceTransitionActionV0 { /// try from borrowed @@ -43,12 +44,35 @@ impl DocumentReplaceTransitionActionV0 { data, .. } = document_replace_transition; - let base = + let base_action_validation_result = DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_replacement_token_cost(), + |document_type| document_type.document_creation_token_cost(), + "replace", )?; + + let base = match base_action_validation_result.is_valid() { + true => base_action_validation_result.into_data()?, + false => { + let bump_action = + BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition( + base, + owner_id, + user_fee_increase, + ); + let batched_action = + BatchedTransitionAction::BumpIdentityDataContractNonce(bump_action); + + return Ok(( + ConsensusValidationResult::new_with_data_and_errors( + batched_action, + base_action_validation_result.errors, + ), + FeeResult::default(), + )); + } + }; let updated_at = if base.document_type_field_is_required(property_names::UPDATED_AT)? { Some(block_info.time_ms) } else { @@ -86,9 +110,9 @@ impl DocumentReplaceTransitionActionV0 { transferred_at_core_block_height: originally_transferred_at_core_block_height, data: data.clone(), } - .into(), - )) .into(), + )) + .into(), FeeResult::default(), )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs index cd4c9e9f50e..a5035f8951e 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/transformer.rs @@ -28,14 +28,16 @@ impl DocumentTransferTransitionAction { Error, > { match document_transfer_transition { - DocumentTransferTransition::V0(v0) => DocumentTransferTransitionActionV0::try_from_borrowed_document_transfer_transition( + DocumentTransferTransition::V0(v0) => { + DocumentTransferTransitionActionV0::try_from_borrowed_document_transfer_transition( v0, owner_id, original_document, block_info, user_fee_increase, get_data_contract, - ), + ) + } } } } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs index 5fddcec3a09..ece299e63b0 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs @@ -14,6 +14,7 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_transfer_transition_action::v0::DocumentTransferTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentTransferTransitionActionV0 { /// try from borrowed @@ -36,13 +37,36 @@ impl DocumentTransferTransitionActionV0 { recipient_owner_id, .. } = document_transfer_transition; - let base = + let base_action_validation_result = DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_transfer_token_cost(), + |document_type| document_type.document_creation_token_cost(), + "transfer", )?; + let base = match base_action_validation_result.is_valid() { + true => base_action_validation_result.into_data()?, + false => { + let bump_action = + BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition( + base, + owner_id, + user_fee_increase, + ); + let batched_action = + BatchedTransitionAction::BumpIdentityDataContractNonce(bump_action); + + return Ok(( + ConsensusValidationResult::new_with_data_and_errors( + batched_action, + base_action_validation_result.errors, + ), + FeeResult::default(), + )); + } + }; + let mut modified_document = original_document; modified_document.set_owner_id(*recipient_owner_id); @@ -70,9 +94,9 @@ impl DocumentTransferTransitionActionV0 { base, document: modified_document, } - .into(), - )) .into(), + )) + .into(), FeeResult::default(), )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs index 3ba651e5137..aa0df3b5c4a 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs @@ -14,6 +14,7 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransition use crate::state_transition_action::batch::batched_transition::document_transition::document_update_price_transition_action::v0::DocumentUpdatePriceTransitionActionV0; use crate::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::{DocumentBaseTransitionAction, DocumentBaseTransitionActionAccessorsV0}; use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use crate::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction; impl DocumentUpdatePriceTransitionActionV0 { /// try from borrowed @@ -32,13 +33,36 @@ impl DocumentUpdatePriceTransitionActionV0 { Error, > { let DocumentUpdatePriceTransitionV0 { base, price, .. } = document_update_price_transition; - let base = + let base_action_validation_result = DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_update_price_token_cost(), + |document_type| document_type.document_creation_token_cost(), + "update_price", )?; + let base = match base_action_validation_result.is_valid() { + true => base_action_validation_result.into_data()?, + false => { + let bump_action = + BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition( + base, + owner_id, + user_fee_increase, + ); + let batched_action = + BatchedTransitionAction::BumpIdentityDataContractNonce(bump_action); + + return Ok(( + ConsensusValidationResult::new_with_data_and_errors( + batched_action, + base_action_validation_result.errors, + ), + FeeResult::default(), + )); + } + }; + let mut modified_document = original_document; modified_document.set_u64(PRICE, *price); @@ -63,9 +87,9 @@ impl DocumentUpdatePriceTransitionActionV0 { base, document: modified_document, } - .into(), - )) .into(), + )) + .into(), FeeResult::default(), )) } diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs index 0286df9c402..a16c5b81159 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs @@ -39,45 +39,49 @@ impl BatchedTransitionAction { } } /// as_document_action - pub fn as_document_action(&self) -> Result<&DocumentTransitionAction, ProtocolError> { - match self { - BatchedTransitionAction::DocumentAction(action) => Ok(action), - other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { - expected: "DocumentAction", - found: other.variant_name(), - }), - } + pub fn as_document_action(&self) -> Result<&DocumentTransitionAction, ProtocolError> { + match self { + BatchedTransitionAction::DocumentAction(action) => Ok(action), + other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { + expected: "DocumentAction", + found: other.variant_name(), + }), } + } /// as_token_action - pub fn as_token_action(&self) -> Result<&TokenTransitionAction, ProtocolError> { - match self { - BatchedTransitionAction::TokenAction(action) => Ok(action), - other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { - expected: "TokenAction", - found: other.variant_name(), - }), - } + pub fn as_token_action(&self) -> Result<&TokenTransitionAction, ProtocolError> { + match self { + BatchedTransitionAction::TokenAction(action) => Ok(action), + other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { + expected: "TokenAction", + found: other.variant_name(), + }), } + } /// as_bump_identity_nonce_action - pub fn as_bump_identity_nonce_action(&self) -> Result<&BumpIdentityDataContractNonceAction, ProtocolError> { - match self { - BatchedTransitionAction::BumpIdentityDataContractNonce(action) => Ok(action), - other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { - expected: "BumpIdentityDataContractNonce", - found: other.variant_name(), - }), - } + pub fn as_bump_identity_nonce_action( + &self, + ) -> Result<&BumpIdentityDataContractNonceAction, ProtocolError> { + match self { + BatchedTransitionAction::BumpIdentityDataContractNonce(action) => Ok(action), + other => Err(ProtocolError::InvalidBatchedTransitionActionVariant { + expected: "BumpIdentityDataContractNonce", + found: other.variant_name(), + }), } + } - /// Helper method to get the variant name for diagnostics. - fn variant_name(&self) -> &'static str { - match self { - BatchedTransitionAction::DocumentAction(_) => "DocumentAction", - BatchedTransitionAction::TokenAction(_) => "TokenAction", - BatchedTransitionAction::BumpIdentityDataContractNonce(_) => "BumpIdentityDataContractNonce", + /// Helper method to get the variant name for diagnostics. + fn variant_name(&self) -> &'static str { + match self { + BatchedTransitionAction::DocumentAction(_) => "DocumentAction", + BatchedTransitionAction::TokenAction(_) => "TokenAction", + BatchedTransitionAction::BumpIdentityDataContractNonce(_) => { + "BumpIdentityDataContractNonce" } } + } } diff --git a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs index d441551783b..de3f038ce0c 100644 --- a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs +++ b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs @@ -97,7 +97,15 @@ impl UpdatePriceOfDocument for Document { settings: Option, ) -> Result { let state_transition = self - .update_price_of_document(price, sdk, document_type, identity_public_key, token_payment_info, signer, None) + .update_price_of_document( + price, + sdk, + document_type, + identity_public_key, + token_payment_info, + signer, + None, + ) .await?; Self::wait_for_response(sdk, state_transition, settings).await diff --git a/packages/wasm-dpp/src/document/factory.rs b/packages/wasm-dpp/src/document/factory.rs index a9380870dcb..4d954c4287f 100644 --- a/packages/wasm-dpp/src/document/factory.rs +++ b/packages/wasm-dpp/src/document/factory.rs @@ -22,9 +22,9 @@ use crate::{ }; use dpp::identifier::Identifier; use dpp::state_transition::batch_transition::batched_transition::document_transition_action_type::DocumentTransitionActionType; +use dpp::tokens::token_payment_info::TokenPaymentInfo; use dpp::version::PlatformVersion; use std::convert::TryFrom; -use dpp::tokens::token_payment_info::TokenPaymentInfo; #[wasm_bindgen(js_name=DocumentTransitions)] #[derive(Debug, Default)] @@ -163,7 +163,12 @@ impl DocumentFactoryWASM { )> = documents_by_action .iter() .map(|(action_type, documents)| { - let documents_with_refs: Vec<(Document, DocumentTypeRef, Bytes32, Option)> = documents + let documents_with_refs: Vec<( + Document, + DocumentTypeRef, + Bytes32, + Option, + )> = documents .iter() .map(|extended_document| { ( From 548e6b286b5e0c24c3e9e186457d3ece87e250b9 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 10:00:25 +0700 Subject: [PATCH 07/18] fixes --- .../platform_serialization_conversion/mod.rs | 3 +-- .../batch_transition/document_transition/mod.rs | 1 - .../src/errors/consensus/consensus_error.rs | 13 +++++++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs b/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs index 40fc1025a1b..e3a112c47e9 100644 --- a/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs +++ b/packages/rs-dpp/src/document/serialization_traits/platform_serialization_conversion/mod.rs @@ -110,9 +110,8 @@ mod tests { use crate::data_contract::accessors::v0::DataContractV0Getters; use crate::data_contract::document_type::random_document::CreateRandomDocument; use crate::document::serialization_traits::DocumentPlatformConversionMethodsV0; - use crate::document::{Document, DocumentV0Setters}; + use crate::document::Document; use crate::tests::json_document::json_document_to_contract; - use platform_value::Value; use platform_version::version::PlatformVersion; #[test] diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs index c324202d2b9..dee9cb76b95 100644 --- a/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/document_transition/mod.rs @@ -19,7 +19,6 @@ use wasm_bindgen::prelude::*; use dpp::fee::Credits; use dpp::platform_value::converter::serde_json::BTreeValueJsonConverter; use dpp::prelude::Revision; -use dpp::state_transition::batch_transition::document_base_transition::DocumentBaseTransition; use dpp::state_transition::batch_transition::document_replace_transition::v0::v0_methods::DocumentReplaceTransitionV0Methods; use dpp::state_transition::batch_transition::batched_transition::document_purchase_transition::v0::v0_methods::DocumentPurchaseTransitionV0Methods; use dpp::state_transition::batch_transition::batched_transition::document_transfer_transition::v0::v0_methods::DocumentTransferTransitionV0Methods; diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 738f1505d17..33d3d1b2d13 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError, }; use wasm_bindgen::{JsError, JsValue}; -use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; +use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError; use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; @@ -84,7 +84,7 @@ use dpp::consensus::state::identity::no_transfer_key_for_core_withdrawal_availab use dpp::consensus::state::identity::RecipientIdentityDoesNotExistError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; -use dpp::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountNotFrozenError, IdentityTokenAccountFrozenError, TokenIsPausedError, IdentityTokenAccountAlreadyFrozenError, UnauthorizedTokenActionError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, TokenMintPastMaxSupplyError, NewTokensDestinationIdentityDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, InvalidGroupPositionError, TokenAlreadyPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, TokenTransferRecipientIdentityNotExistError, PreProgrammedDistributionTimestampInPastError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError}; +use dpp::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountNotFrozenError, IdentityTokenAccountFrozenError, TokenIsPausedError, IdentityTokenAccountAlreadyFrozenError, UnauthorizedTokenActionError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, TokenMintPastMaxSupplyError, NewTokensDestinationIdentityDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, InvalidGroupPositionError, TokenAlreadyPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, TokenTransferRecipientIdentityNotExistError, PreProgrammedDistributionTimestampInPastError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError, IdentityTryingToPayWithWrongTokenError}; use dpp::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; @@ -396,6 +396,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::RequiredTokenPaymentInfoNotSetError(e) => { generic_consensus_error!(RequiredTokenPaymentInfoNotSetError, e).into() } + StateError::IdentityTryingToPayWithWrongTokenError(e) => { + generic_consensus_error!(IdentityTryingToPayWithWrongTokenError, e).into() + } } } @@ -752,6 +755,12 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::UnknownGasFeesPaidByError(e) => { generic_consensus_error!(UnknownGasFeesPaidByError, e).into() } + BasicError::UnknownDocumentActionTokenEffectError(e) => { + generic_consensus_error!(UnknownDocumentActionTokenEffectError, e).into() + } + BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError(e) => { + generic_consensus_error!(TokenPaymentByBurningOnlyAllowedOnInternalTokenError, e).into() + } } } From f508b5fd123e3cb2a07d80f647cb382ecf8f1c18 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 10:19:50 +0700 Subject: [PATCH 08/18] fixes --- packages/check-features/src/main.rs | 8 ++-- .../src/core_types/validator_set/v0/mod.rs | 3 +- .../class_methods/try_from_schema/v0/mod.rs | 5 ++- .../class_methods/try_from_schema/v1/mod.rs | 43 ++++++++++++------- .../basic/json_schema_error/error.rs | 2 + .../basic/json_schema_error/error_data.rs | 2 + .../rs-dpp/src/identity/identity_factory.rs | 7 ++- .../document_create_transition/convertible.rs | 2 +- .../document/batch_transition/methods/mod.rs | 1 + .../batch_transition/methods/v0/mod.rs | 1 + .../batch_transition/v0/v0_methods.rs | 1 + .../batch_transition/v1/v0_methods.rs | 1 + .../rs-dpp/src/tokens/gas_fees_paid_by.rs | 1 + .../src/tokens/token_payment_info/mod.rs | 6 ++- .../src/tokens/token_payment_info/v0/mod.rs | 1 + 15 files changed, 58 insertions(+), 26 deletions(-) diff --git a/packages/check-features/src/main.rs b/packages/check-features/src/main.rs index c8a876a1f32..9ee805689d3 100644 --- a/packages/check-features/src/main.rs +++ b/packages/check-features/src/main.rs @@ -4,11 +4,11 @@ use toml::Value; fn main() { let crates = [ - ("rs-sdk", vec![]), - ("rs-drive-abci", vec![]), + // ("rs-sdk", vec![]), + // ("rs-drive-abci", vec![]), ("rs-dpp", vec![]), - ("rs-drive", vec![]), - ("rs-drive-proof-verifier", vec![]), + // ("rs-drive", vec![]), + // ("rs-drive-proof-verifier", vec![]), ]; for (specific_crate, to_ignore) in crates { diff --git a/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs b/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs index 0774fe8c74c..8366ab31932 100644 --- a/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs +++ b/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs @@ -9,6 +9,7 @@ use bincode::error::EncodeError; #[cfg(feature = "core-types-serialization")] use bincode::{BorrowDecode, Decode, Encode}; use dashcore::blsful::Bls12381G2Impl; +#[cfg(feature = "core-types-serialization")] use dashcore::hashes::Hash; use dashcore::{ProTxHash, QuorumHash}; use itertools::Itertools; @@ -18,7 +19,7 @@ use std::collections::BTreeMap; use std::fmt; use std::fmt::{Debug, Display, Formatter}; -/// The validator set is only slightly different from a quorum as it does not contain non valid +/// The validator set is only slightly different from a quorum as it does not contain non-valid /// members #[derive(Clone, Eq, PartialEq)] #[cfg_attr( diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs index 120493f020a..7915f665844 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs @@ -8,7 +8,9 @@ use crate::consensus::basic::data_contract::{ use crate::consensus::ConsensusError; use crate::data_contract::document_type::index::Index; use crate::data_contract::document_type::index_level::IndexLevel; -use crate::data_contract::document_type::property::{DocumentProperty, DocumentPropertyType}; +use crate::data_contract::document_type::property::DocumentProperty; +#[cfg(feature = "validation")] +use crate::data_contract::document_type::property::DocumentPropertyType; #[cfg(feature = "validation")] use crate::data_contract::document_type::schema::validate_max_depth; use crate::data_contract::document_type::v0::DocumentTypeV0; @@ -32,6 +34,7 @@ use crate::consensus::basic::document::MissingPositionsInDocumentTypePropertiesE use crate::consensus::basic::BasicError; use crate::data_contract::config::v0::DataContractConfigGettersV0; use crate::data_contract::config::DataContractConfig; +#[cfg(feature = "validation")] use crate::data_contract::document_type::class_methods::try_from_schema::{ MAX_INDEXED_BYTE_ARRAY_PROPERTY_LENGTH, MAX_INDEXED_STRING_PROPERTY_LENGTH, NOT_ALLOWED_SYSTEM_PROPERTIES, SYSTEM_PROPERTIES, diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs index b39f88d383d..2eb3a7897c6 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs @@ -8,7 +8,9 @@ use crate::consensus::basic::data_contract::{ use crate::consensus::ConsensusError; use crate::data_contract::document_type::index::Index; use crate::data_contract::document_type::index_level::IndexLevel; -use crate::data_contract::document_type::property::{DocumentProperty, DocumentPropertyType}; +use crate::data_contract::document_type::property::DocumentProperty; +#[cfg(feature = "validation")] +use crate::data_contract::document_type::property::DocumentPropertyType; #[cfg(feature = "validation")] use crate::data_contract::document_type::schema::validate_max_depth; #[cfg(feature = "validation")] @@ -26,6 +28,7 @@ use crate::consensus::basic::data_contract::ContestedUniqueIndexOnMutableDocumen use crate::consensus::basic::data_contract::ContestedUniqueIndexWithUniqueIndexError; #[cfg(any(test, feature = "validation"))] use crate::consensus::basic::data_contract::InvalidDocumentTypeNameError; +#[cfg(feature = "validation")] use crate::consensus::basic::data_contract::TokenPaymentByBurningOnlyAllowedOnInternalTokenError; #[cfg(feature = "validation")] use crate::consensus::basic::document::MissingPositionsInDocumentTypePropertiesError; @@ -34,8 +37,12 @@ use crate::consensus::basic::BasicError; use crate::data_contract::config::v0::DataContractConfigGettersV0; use crate::data_contract::config::DataContractConfig; use crate::data_contract::document_type::class_methods::try_from_schema::{ - insert_values, insert_values_nested, MAX_INDEXED_BYTE_ARRAY_PROPERTY_LENGTH, - MAX_INDEXED_STRING_PROPERTY_LENGTH, NOT_ALLOWED_SYSTEM_PROPERTIES, SYSTEM_PROPERTIES, + insert_values, insert_values_nested, +}; +#[cfg(feature = "validation")] +use crate::data_contract::document_type::class_methods::try_from_schema::{ + MAX_INDEXED_BYTE_ARRAY_PROPERTY_LENGTH, MAX_INDEXED_STRING_PROPERTY_LENGTH, + NOT_ALLOWED_SYSTEM_PROPERTIES, SYSTEM_PROPERTIES, }; use crate::data_contract::document_type::class_methods::{ consensus_or_protocol_data_contract_error, consensus_or_protocol_value_error, @@ -568,20 +575,24 @@ impl DocumentTypeV1 { .transpose()? .unwrap_or(DocumentActionTokenEffect::TransferTokenToContractOwner); - // If contractId is present and user tries to burn, bail out: - if contract_id.is_some() && effect == DocumentActionTokenEffect::BurnToken { - return Err(ProtocolError::ConsensusError( - ConsensusError::BasicError( - BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError( - TokenPaymentByBurningOnlyAllowedOnInternalTokenError::new( - contract_id.unwrap(), - token_contract_position, - key.to_string(), + #[cfg(feature = "validation")] + if full_validation { + + // If contractId is present and user tries to burn, bail out: + if contract_id.is_some() && effect == DocumentActionTokenEffect::BurnToken { + return Err(ProtocolError::ConsensusError( + ConsensusError::BasicError( + BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError( + TokenPaymentByBurningOnlyAllowedOnInternalTokenError::new( + contract_id.unwrap(), + token_contract_position, + key.to_string(), + ), ), - ), - ) - .into(), - )); + ) + .into(), + )); + } } // Extract an optional string and map it to the enum, defaulting if missing or unrecognized. diff --git a/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error.rs b/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error.rs index cdfdb081046..780998dc297 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "json-schema-validation")] use crate::consensus::basic::json_schema_error::error_data::JsonSchemaErrorData; use crate::consensus::basic::BasicError; use crate::consensus::ConsensusError; @@ -7,6 +8,7 @@ use bincode::{Decode, Encode}; use jsonschema::ValidationError; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use platform_value::Value; +#[cfg(feature = "json-schema-validation")] use serde_json::Value as JsonValue; use thiserror::Error; diff --git a/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error_data.rs b/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error_data.rs index a8468aec37f..ad654612356 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error_data.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/json_schema_error/error_data.rs @@ -6,7 +6,9 @@ use jsonschema::paths::PathChunk; use jsonschema::ValidationError; use serde::{Deserialize, Serialize}; use serde_json::Value; +#[cfg(feature = "json-schema-validation")] use std::fmt::Write; +#[cfg(feature = "json-schema-validation")] use std::ops::Deref; #[derive(Debug, Serialize, Default, Deserialize)] diff --git a/packages/rs-dpp/src/identity/identity_factory.rs b/packages/rs-dpp/src/identity/identity_factory.rs index 48f73698181..2ec10511c20 100644 --- a/packages/rs-dpp/src/identity/identity_factory.rs +++ b/packages/rs-dpp/src/identity/identity_factory.rs @@ -23,8 +23,11 @@ use crate::consensus::basic::BasicError; use crate::consensus::ConsensusError; #[cfg(all(feature = "state-transitions", feature = "client"))] use crate::identity::accessors::IdentityGettersV0; - -#[cfg(all(feature = "validation", feature = "identity-value-conversion"))] +#[cfg(all( + feature = "identity-serialization", + feature = "client", + feature = "validation" +))] use crate::identity::conversion::platform_value::IdentityPlatformValueConversionMethodsV0; #[cfg(all(feature = "state-transitions", feature = "client"))] use crate::identity::core_script::CoreScript; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs index e3ca40a136b..bfa829a274a 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/convertible.rs @@ -35,7 +35,7 @@ use crate::ProtocolError; feature = "state-transition-value-conversion" ))] use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; -#[cfg(any(feature = "state-transition-json-conversion"))] +#[cfg(feature = "state-transition-json-conversion")] use platform_value::btreemap_extensions::{ BTreeValueMapHelper, BTreeValueMapReplacementPathHelper, }; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs index 00b8c30772d..7404683fd53 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs @@ -30,6 +30,7 @@ use crate::state_transition::batch_transition::{BatchTransitionV0, BatchTransiti use crate::state_transition::StateTransition; #[cfg(feature = "state-transition-signing")] use crate::tokens::emergency_action::TokenEmergencyAction; +#[cfg(feature = "state-transition-signing")] use crate::tokens::token_payment_info::TokenPaymentInfo; #[cfg(feature = "state-transition-signing")] use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs index baddc555aeb..acb26f272ac 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v0/mod.rs @@ -22,6 +22,7 @@ use platform_version::version::{FeatureVersion, PlatformVersion}; use std::convert::TryFrom; use crate::state_transition::batch_transition::batched_transition::{BatchedTransition, BatchedTransitionRef}; use crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_transition::DocumentTransitionV0Methods; +#[cfg(feature = "state-transition-signing")] use crate::tokens::token_payment_info::TokenPaymentInfo; pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0 { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs index ffa94ae3476..cbdd6fa1cd9 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v0/v0_methods.rs @@ -39,6 +39,7 @@ use crate::state_transition::batch_transition::batched_transition::document_purc use crate::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; use crate::state_transition::batch_transition::resolvers::v0::BatchTransitionResolversV0; use crate::state_transition::state_transitions::document::batch_transition::batched_transition::document_transition::DocumentTransitionV0Methods; +#[cfg(feature = "state-transition-signing")] use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentsBatchTransitionAccessorsV0 for BatchTransitionV0 { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs index 73ad8f3f1e2..833f1e43727 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs @@ -85,6 +85,7 @@ use crate::state_transition::batch_transition::token_unfreeze_transition::TokenU use crate::tokens::emergency_action::TokenEmergencyAction; #[cfg(feature = "state-transition-signing")] use crate::tokens::{PrivateEncryptedNote, SharedEncryptedNote}; +#[cfg(feature = "state-transition-signing")] use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentsBatchTransitionAccessorsV0 for BatchTransitionV1 { diff --git a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs index ba0644e7118..004266e1859 100644 --- a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs +++ b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs @@ -4,6 +4,7 @@ use crate::consensus::ConsensusError; use crate::ProtocolError; use bincode_derive::{Decode, Encode}; use derive_more::Display; +#[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs index e4127bd0347..91a95f7a9fd 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -9,7 +9,10 @@ use bincode_derive::{Decode, Encode}; use derive_more::{Display, From}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use platform_value::btreemap_extensions::BTreeValueMapHelper; -use platform_value::{Error, Identifier, Value}; +#[cfg(feature = "state-transition-value-conversion")] +use platform_value::Error; +use platform_value::{Identifier, Value}; +#[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -131,6 +134,7 @@ impl TryFrom> for TokenPaymentInfo { } } +#[cfg(feature = "state-transition-value-conversion")] impl TryFrom for Value { type Error = Error; fn try_from(value: TokenPaymentInfo) -> Result { diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs index dd8a93f13f1..36376c1fe7f 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs @@ -9,6 +9,7 @@ use bincode_derive::{Decode, Encode}; use derive_more::Display; use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; use platform_value::{Identifier, Value}; +#[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; From fd2059be3fbac34b7663cfdce20c544238da74b1 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 10:24:50 +0700 Subject: [PATCH 09/18] clippy fixes --- .../src/data_contract/document_type/class_methods/mod.rs | 2 +- .../token/identity_trying_to_pay_with_wrong_token_error.rs | 4 ++-- .../document_base_transition/from_document.rs | 1 + .../document_create_transition/from_document.rs | 1 + .../document_delete_transition/from_document.rs | 1 + .../document_purchase_transition/from_document.rs | 1 + .../document_replace_transition/from_document.rs | 1 + .../document_transfer_transition/from_document.rs | 1 + .../document_update_price_transition/from_document.rs | 1 + packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs | 2 +- 10 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs index 1a38953a784..77a2dca60c6 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/mod.rs @@ -34,6 +34,6 @@ fn consensus_or_protocol_value_error(platform_value_error: platform_value::Error } #[cfg(not(feature = "validation"))] { - ProtocolError::ValueError(platform_value_error.into()) + ProtocolError::ValueError(platform_value_error) } } diff --git a/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs b/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs index ea6c8ebf162..89e2e730562 100644 --- a/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/token/identity_trying_to_pay_with_wrong_token_error.rs @@ -39,7 +39,7 @@ impl IdentityTryingToPayWithWrongTokenError { } pub fn expected_contract_id(&self) -> Option { - self.expected_contract_id.clone() + self.expected_contract_id } pub fn expected_token_contract_position(&self) -> TokenContractPosition { @@ -51,7 +51,7 @@ impl IdentityTryingToPayWithWrongTokenError { } pub fn actual_contract_id(&self) -> Option { - self.actual_contract_id.clone() + self.actual_contract_id } pub fn actual_token_contract_position(&self) -> TokenContractPosition { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs index b6d464d1d91..d394d50727d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_base_transition/from_document.rs @@ -9,6 +9,7 @@ use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; impl DocumentBaseTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: &Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs index dd05ddf03c6..1916f706032 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/from_document.rs @@ -8,6 +8,7 @@ use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; impl DocumentCreateTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs index 89ff4eafe77..4af388b6b76 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_delete_transition/from_document.rs @@ -9,6 +9,7 @@ use crate::state_transition::batch_transition::batched_transition::DocumentDelet use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentDeleteTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs index a559083cf35..5c92946a2fb 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_purchase_transition/from_document.rs @@ -10,6 +10,7 @@ use crate::state_transition::batch_transition::batched_transition::DocumentPurch use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentPurchaseTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs index 76adba03197..373ccf4aa00 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/from_document.rs @@ -8,6 +8,7 @@ use crate::ProtocolError; use platform_version::version::{FeatureVersion, PlatformVersion}; impl DocumentReplaceTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs index b75d89d33f1..5b16c302d6c 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_transfer_transition/from_document.rs @@ -10,6 +10,7 @@ use platform_value::Identifier; use platform_version::version::{FeatureVersion, PlatformVersion}; impl DocumentTransferTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs index 90a3216525d..331f2c677cb 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_update_price_transition/from_document.rs @@ -9,6 +9,7 @@ use crate::state_transition::batch_transition::batched_transition::document_upda use crate::tokens::token_payment_info::TokenPaymentInfo; impl DocumentUpdatePriceTransition { + #[allow(clippy::too_many_arguments)] pub fn from_document( document: Document, document_type: DocumentTypeRef, diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs index 36376c1fe7f..c52720a414a 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs @@ -42,7 +42,7 @@ pub struct TokenPaymentInfoV0 { /// If: /// - a client does not have this set /// - and the data contract allows the price of NFTs to be changed by the data contract's owner or allowed party. - /// Then: + /// Then: /// - The user could see the cost changed on them pub maximum_token_cost: Option, /// Who pays the gas fees, this needs to match what the contract allows From c7e44c7d9474c3fbde6c092d3c2d671ccaefefd9 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 10:56:30 +0700 Subject: [PATCH 10/18] more fixes --- .../class_methods/try_from_schema/v1/mod.rs | 26 +++++++------- .../batch/tests/document/deletion.rs | 34 ++++++++++++++++--- .../batch/tests/document/nft.rs | 26 ++++++++++++-- .../batch/tests/document/replacement.rs | 18 ++++++++-- .../batch/tests/document/transfer.rs | 18 ++++++++-- .../transformer.rs | 1 + .../v0/transformer.rs | 1 + .../v0/transformer.rs | 2 +- .../v0/transformer.rs | 2 +- .../v0/transformer.rs | 2 +- .../v0/transformer.rs | 2 +- .../v0/transformer.rs | 2 +- .../batch/batched_transition/mod.rs | 1 - 13 files changed, 106 insertions(+), 29 deletions(-) diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs index 2eb3a7897c6..6a6087aed2a 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs @@ -579,19 +579,21 @@ impl DocumentTypeV1 { if full_validation { // If contractId is present and user tries to burn, bail out: - if contract_id.is_some() && effect == DocumentActionTokenEffect::BurnToken { - return Err(ProtocolError::ConsensusError( - ConsensusError::BasicError( - BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError( - TokenPaymentByBurningOnlyAllowedOnInternalTokenError::new( - contract_id.unwrap(), - token_contract_position, - key.to_string(), + if let Some(contract_id) = contract_id { + if effect == DocumentActionTokenEffect::BurnToken { + return Err(ProtocolError::ConsensusError( + ConsensusError::BasicError( + BasicError::TokenPaymentByBurningOnlyAllowedOnInternalTokenError( + TokenPaymentByBurningOnlyAllowedOnInternalTokenError::new( + contract_id, + token_contract_position, + key.to_string(), + ), ), - ), - ) - .into(), - )); + ) + .into(), + )); + } } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs index ed6b5edacc1..d5d511abb30 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs @@ -3,6 +3,8 @@ use super::*; mod deletion_tests { use super::*; use crate::execution::validation::state_transition::tests::create_card_game_internal_token_contract_with_owner_identity_burn_tokens; + use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; + use dpp::tokens::token_payment_info::TokenPaymentInfo; #[test] fn test_document_delete_on_document_type_that_is_mutable_and_can_be_deleted() { @@ -809,7 +811,13 @@ mod deletion_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -869,7 +877,13 @@ mod deletion_tests { &key, 3, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 1, + minimum_token_cost: None, + maximum_token_cost: Some(1), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -978,7 +992,13 @@ mod deletion_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -1038,7 +1058,13 @@ mod deletion_tests { &key, 3, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 1, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs index f61445ea309..d90c717889a 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/nft.rs @@ -3,6 +3,8 @@ use super::*; mod nft_tests { use super::*; use crate::test::helpers::fast_forward_to_block::fast_forward_to_block; + use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; + use dpp::tokens::token_payment_info::TokenPaymentInfo; #[test] fn test_document_set_price_on_document_without_ability_to_purchase() { let platform_version = PlatformVersion::latest(); @@ -2903,7 +2905,13 @@ mod nft_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: Some(10), + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -3000,7 +3008,13 @@ mod nft_tests { &key, 3, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 1, + minimum_token_cost: None, + maximum_token_cost: Some(1), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -3092,7 +3106,13 @@ mod nft_tests { &recipient_key, 1, // 1 because he's never done anything 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: Some(2), + maximum_token_cost: Some(3), + gas_fees_paid_by: Default::default(), + })), &recipient_signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs index b08c522f2db..ed72f0c583b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs @@ -5,6 +5,8 @@ mod replacement_tests { use crate::test::helpers::fast_forward_to_block::fast_forward_to_block; use dpp::identifier::Identifier; use dpp::prelude::IdentityNonce; + use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; + use dpp::tokens::token_payment_info::TokenPaymentInfo; use std::collections::BTreeMap; #[test] @@ -2018,7 +2020,13 @@ mod replacement_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -2065,7 +2073,13 @@ mod replacement_tests { &key, 3, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 1, + minimum_token_cost: None, + maximum_token_cost: Some(2), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs index a72e1bd8373..8a0e7ea99fd 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/transfer.rs @@ -2,6 +2,8 @@ use super::*; mod transfer_tests { use super::*; + use dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0; + use dpp::tokens::token_payment_info::TokenPaymentInfo; #[test] fn test_document_transfer_on_document_type_that_is_transferable_that_has_no_owner_indices() { @@ -1098,7 +1100,13 @@ mod transfer_tests { &key, 2, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 0, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, @@ -1192,7 +1200,13 @@ mod transfer_tests { &key, 3, 0, - None, + Some(TokenPaymentInfo::V0(TokenPaymentInfoV0 { + payment_token_contract_id: None, + token_contract_position: 1, + minimum_token_cost: None, + maximum_token_cost: Some(10), + gas_fees_paid_by: Default::default(), + })), &signer, platform_version, None, diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs index 34e3164787c..cce4ec18856 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/transformer.rs @@ -15,6 +15,7 @@ use crate::state_transition_action::batch::batched_transition::document_transiti impl DocumentCreateTransitionAction { /// from_document_borrowed_create_transition_with_contract_lookup + #[allow(clippy::too_many_arguments)] pub fn try_from_document_borrowed_create_transition_with_contract_lookup( drive: &Drive, owner_id: Identifier, diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs index cb89a46b4d4..7fdbaba02e9 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs @@ -23,6 +23,7 @@ use crate::state_transition_action::system::bump_identity_data_contract_nonce_ac impl DocumentCreateTransitionActionV0 { /// try from borrowed document create transition with contract lookup + #[allow(clippy::too_many_arguments)] pub fn try_from_borrowed_document_create_transition_with_contract_lookup( drive: &Drive, owner_id: Identifier, diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs index 82129c18b20..ec815461626 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/v0/transformer.rs @@ -33,7 +33,7 @@ impl DocumentDeleteTransitionActionV0 { DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_creation_token_cost(), + |document_type| document_type.document_deletion_token_cost(), "delete", )?; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs index 208a3ea2f36..c0a706aa30c 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_purchase_transition_action/v0/transformer.rs @@ -38,7 +38,7 @@ impl DocumentPurchaseTransitionActionV0 { DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_creation_token_cost(), + |document_type| document_type.document_purchase_token_cost(), "purchase", )?; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs index 367974151d9..8642bc34221 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs @@ -48,7 +48,7 @@ impl DocumentReplaceTransitionActionV0 { DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_creation_token_cost(), + |document_type| document_type.document_replacement_token_cost(), "replace", )?; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs index ece299e63b0..17264725946 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_transfer_transition_action/v0/transformer.rs @@ -41,7 +41,7 @@ impl DocumentTransferTransitionActionV0 { DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_creation_token_cost(), + |document_type| document_type.document_transfer_token_cost(), "transfer", )?; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs index aa0df3b5c4a..f18dca6085d 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_update_price_transition_action/v0/transformer.rs @@ -37,7 +37,7 @@ impl DocumentUpdatePriceTransitionActionV0 { DocumentBaseTransitionAction::try_from_borrowed_base_transition_with_contract_lookup( base, get_data_contract, - |document_type| document_type.document_creation_token_cost(), + |document_type| document_type.document_update_price_token_cost(), "update_price", )?; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs index a16c5b81159..d0c45c1ac86 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/mod.rs @@ -61,7 +61,6 @@ impl BatchedTransitionAction { } /// as_bump_identity_nonce_action - pub fn as_bump_identity_nonce_action( &self, ) -> Result<&BumpIdentityDataContractNonceAction, ProtocolError> { From 187ce0f6dfd7585c22f1b99bc62da7713b45f5f3 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 11:08:03 +0700 Subject: [PATCH 11/18] more fixes --- .../state_transitions/batch/transformer/v0/mod.rs | 2 +- .../document_delete_transition_action/transformer.rs | 2 +- packages/rs-sdk/src/platform/transition/transfer_document.rs | 2 ++ .../rs-sdk/src/platform/transition/update_price_of_document.rs | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs index 726bb7ea680..9540f6a5e79 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs @@ -736,7 +736,7 @@ impl BatchTransitionInternalTransformerV0 for BatchTransition { } } DocumentTransition::Delete(document_delete_transition) => { - let (batched_action, fee_result) = DocumentDeleteTransitionAction::try_from_document_borrowed_create_transition_with_contract_lookup(document_delete_transition, owner_id, user_fee_increase, |_identifier| { + let (batched_action, fee_result) = DocumentDeleteTransitionAction::try_from_document_borrowed_delete_transition_with_contract_lookup(document_delete_transition, owner_id, user_fee_increase, |_identifier| { Ok(data_contract_fetch_info.clone()) })?; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs index d5659d0a203..30e506013b7 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_delete_transition_action/transformer.rs @@ -11,7 +11,7 @@ use crate::state_transition_action::batch::batched_transition::document_transiti impl DocumentDeleteTransitionAction { /// from borrowed - pub fn try_from_document_borrowed_create_transition_with_contract_lookup( + pub fn try_from_document_borrowed_delete_transition_with_contract_lookup( value: &DocumentDeleteTransition, owner_id: Identifier, user_fee_increase: UserFeeIncrease, diff --git a/packages/rs-sdk/src/platform/transition/transfer_document.rs b/packages/rs-sdk/src/platform/transition/transfer_document.rs index f63115c0638..0dae7f03fd9 100644 --- a/packages/rs-sdk/src/platform/transition/transfer_document.rs +++ b/packages/rs-sdk/src/platform/transition/transfer_document.rs @@ -19,6 +19,7 @@ use rs_dapi_client::{DapiRequest, IntoInner}; pub trait TransferDocument: Waitable { /// Transfers a document on platform /// Setting settings to `None` sets default connection behavior + #[allow(clippy::too_many_arguments)] async fn transfer_document_to_identity( &self, recipient_id: Identifier, @@ -31,6 +32,7 @@ pub trait TransferDocument: Waitable { ) -> Result; /// Transfers a document on platform and waits for the response + #[allow(clippy::too_many_arguments)] async fn transfer_document_to_identity_and_wait_for_response( &self, recipient_id: Identifier, diff --git a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs index de3f038ce0c..c3c362bfc86 100644 --- a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs +++ b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs @@ -19,6 +19,7 @@ use dpp::tokens::token_payment_info::TokenPaymentInfo; pub trait UpdatePriceOfDocument: Waitable { /// Updates the price of a document on platform /// Setting settings to `None` sets default connection behavior + #[allow(clippy::too_many_arguments)] async fn update_price_of_document( &self, price: Credits, @@ -31,6 +32,7 @@ pub trait UpdatePriceOfDocument: Waitable { ) -> Result; /// Updates the price of a document on platform and waits for the response + #[allow(clippy::too_many_arguments)] async fn update_price_of_document_and_wait_for_response( &self, price: Credits, From ea22db1d6650e84423a7a24d9038d0f2d1789e54 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 11:12:04 +0700 Subject: [PATCH 12/18] more fixes --- .../src/document/extended_document/v0/mod.rs | 6 ++++++ .../src/tokens/token_payment_info/mod.rs | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/rs-dpp/src/document/extended_document/v0/mod.rs b/packages/rs-dpp/src/document/extended_document/v0/mod.rs index 0b4140b8a51..c2a48a05bac 100644 --- a/packages/rs-dpp/src/document/extended_document/v0/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/v0/mod.rs @@ -27,6 +27,12 @@ use platform_value::btreemap_extensions::{ BTreeValueMapReplacementPathHelper, BTreeValueRemoveFromMapHelper, }; use platform_value::{Bytes32, Identifier, ReplacementType, Value}; +#[cfg( + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ) +)] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs index 91a95f7a9fd..338017a9b53 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -12,7 +12,15 @@ use platform_value::btreemap_extensions::BTreeValueMapHelper; #[cfg(feature = "state-transition-value-conversion")] use platform_value::Error; use platform_value::{Identifier, Value}; -#[cfg(feature = "state-transition-serde-conversion")] +#[cfg( + any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + ) +)] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -32,7 +40,13 @@ pub mod v0; From, )] #[cfg_attr( - feature = "state-transition-serde-conversion", + any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + ), derive(Serialize, Deserialize) )] pub enum TokenPaymentInfo { From 6778dc72ebe5d9add3d4543277ffe72752ad6b24 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 11:12:13 +0700 Subject: [PATCH 13/18] more fixes --- .../src/document/extended_document/v0/mod.rs | 10 ++++------ .../rs-dpp/src/tokens/token_payment_info/mod.rs | 16 +++++++--------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/rs-dpp/src/document/extended_document/v0/mod.rs b/packages/rs-dpp/src/document/extended_document/v0/mod.rs index c2a48a05bac..597a8165cb3 100644 --- a/packages/rs-dpp/src/document/extended_document/v0/mod.rs +++ b/packages/rs-dpp/src/document/extended_document/v0/mod.rs @@ -27,12 +27,10 @@ use platform_value::btreemap_extensions::{ BTreeValueMapReplacementPathHelper, BTreeValueRemoveFromMapHelper, }; use platform_value::{Bytes32, Identifier, ReplacementType, Value}; -#[cfg( - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ) -)] +#[cfg(all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" +))] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs index 338017a9b53..db3df38dcff 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/mod.rs @@ -12,15 +12,13 @@ use platform_value::btreemap_extensions::BTreeValueMapHelper; #[cfg(feature = "state-transition-value-conversion")] use platform_value::Error; use platform_value::{Identifier, Value}; -#[cfg( - any( - feature = "state-transition-serde-conversion", - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" - ), - ) -)] +#[cfg(any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), +))] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; From 19f7163d7e2fd0bf8d7ba1abd5b0ecceabbf11d9 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 11:17:21 +0700 Subject: [PATCH 14/18] small fix --- packages/check-features/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/check-features/src/main.rs b/packages/check-features/src/main.rs index 9ee805689d3..c8a876a1f32 100644 --- a/packages/check-features/src/main.rs +++ b/packages/check-features/src/main.rs @@ -4,11 +4,11 @@ use toml::Value; fn main() { let crates = [ - // ("rs-sdk", vec![]), - // ("rs-drive-abci", vec![]), + ("rs-sdk", vec![]), + ("rs-drive-abci", vec![]), ("rs-dpp", vec![]), - // ("rs-drive", vec![]), - // ("rs-drive-proof-verifier", vec![]), + ("rs-drive", vec![]), + ("rs-drive-proof-verifier", vec![]), ]; for (specific_crate, to_ignore) in crates { From 23f4e89b5ba90489ce4095c37da39ad438fb1f6f Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 11:37:02 +0700 Subject: [PATCH 15/18] small fix --- .../src/tokens/token_payment_info/v0/mod.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs index c52720a414a..8719cba8b26 100644 --- a/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs +++ b/packages/rs-dpp/src/tokens/token_payment_info/v0/mod.rs @@ -9,15 +9,26 @@ use bincode_derive::{Decode, Encode}; use derive_more::Display; use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; use platform_value::{Identifier, Value}; -#[cfg(feature = "state-transition-serde-conversion")] +#[cfg(any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), +))] use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; #[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] #[cfg_attr( - feature = "state-transition-serde-conversion", - derive(Serialize, Deserialize), - serde(rename_all = "camelCase") + any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), + ), + derive(Serialize, Deserialize) )] #[display( "Contract ID: {:?}, Token Position: {:?}, Min Cost: {:?}, Max Cost: {:?}, Gas Fees Paid By: {}", From 6dc2f8864293e92f07c4a425c1a06b79c4bb6f91 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 17:54:57 +0700 Subject: [PATCH 16/18] fix --- packages/rs-dpp/src/tokens/gas_fees_paid_by.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs index 004266e1859..c84798f4e11 100644 --- a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs +++ b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs @@ -4,14 +4,23 @@ use crate::consensus::ConsensusError; use crate::ProtocolError; use bincode_derive::{Decode, Encode}; use derive_more::Display; -#[cfg(feature = "state-transition-serde-conversion")] +#[cfg(any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), +))] use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] -#[cfg_attr( +#[cfg(any( feature = "state-transition-serde-conversion", - derive(Serialize, Deserialize) -)] + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), +))] pub enum GasFeesPaidBy { /// The user pays the gas fees #[default] From 8b08663f072c5fd47d4e0b3fc0baaaef9b1c10aa Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 30 Mar 2025 17:58:09 +0700 Subject: [PATCH 17/18] fix --- packages/rs-dpp/src/tokens/gas_fees_paid_by.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs index c84798f4e11..72d8e1fd565 100644 --- a/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs +++ b/packages/rs-dpp/src/tokens/gas_fees_paid_by.rs @@ -14,13 +14,16 @@ use derive_more::Display; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, Encode, Decode, Default, PartialEq, Display)] -#[cfg(any( - feature = "state-transition-serde-conversion", - all( - feature = "document-serde-conversion", - feature = "data-contract-serde-conversion" +#[cfg_attr( + any( + feature = "state-transition-serde-conversion", + all( + feature = "document-serde-conversion", + feature = "data-contract-serde-conversion" + ), ), -))] + derive(Serialize, Deserialize) +)] pub enum GasFeesPaidBy { /// The user pays the gas fees #[default] From 1b2b075bfcfda5d917d6f0c47761dd33abf54535 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 31 Mar 2025 10:08:34 +0700 Subject: [PATCH 18/18] fixes --- .../meta_schemas/document/v0/document-meta.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json b/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json index b34388a310b..5570d74da3c 100644 --- a/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json +++ b/packages/rs-dpp/schema/meta_schemas/document/v0/document-meta.json @@ -300,18 +300,29 @@ }, "tokenPosition": { "type": "integer", - "minimum": 0 + "minimum": 0, + "maximum": 65535 }, "amount": { "type": "integer", - "minimum": 0 + "minimum": 1, + "maximum": 281474976710655 }, "effect": { "type": "integer", + "enum": [ + 0, + 1 + ], "description": "0 - TransferTokenToContractOwner (default), 1 - Burn" }, "gasFeesPaidBy": { "type": "integer", + "enum": [ + 0, + 1, + 2 + ], "description": "0 - DocumentOwner (default), 1 - ContractOwner, 2 - PreferContractOwner" } },