diff --git a/packages/rs-dpp/src/data_contract/data_contract.rs b/packages/rs-dpp/src/data_contract/data_contract.rs index 151195569d9..3d00fbd2791 100644 --- a/packages/rs-dpp/src/data_contract/data_contract.rs +++ b/packages/rs-dpp/src/data_contract/data_contract.rs @@ -10,6 +10,7 @@ use platform_value::Value; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; +use crate::consensus::basic::document::InvalidDocumentTypeError; use crate::data_contract::contract_config; use crate::data_contract::contract_config::{ ContractConfig, DEFAULT_CONTRACT_CAN_BE_DELETED, DEFAULT_CONTRACT_DOCUMENTS_KEEPS_HISTORY, @@ -18,7 +19,7 @@ use crate::data_contract::contract_config::{ }; use crate::data_contract::get_binary_properties_from_schema::get_binary_properties; -use crate::util::cbor_value::{CborBTreeMapHelper, CborCanonicalMap}; +use crate::util::cbor_value::CborCanonicalMap; use crate::util::deserializer; use crate::util::deserializer::SplitProtocolVersionOutcome; use crate::util::json_value::{JsonValueExt, ReplaceWith}; @@ -319,10 +320,10 @@ impl DataContract { .documents .get(doc_type) .ok_or(ProtocolError::DataContractError( - DataContractError::InvalidDocumentTypeError { - doc_type: doc_type.to_owned(), - data_contract: self.clone(), - }, + DataContractError::InvalidDocumentTypeError(InvalidDocumentTypeError::new( + doc_type.to_owned(), + self.id.clone(), + )), ))?; Ok(document) } @@ -330,10 +331,10 @@ impl DataContract { pub fn get_document_schema_ref(&self, doc_type: &str) -> Result { if !self.is_document_defined(doc_type) { return Err(ProtocolError::DataContractError( - DataContractError::InvalidDocumentTypeError { - doc_type: doc_type.to_owned(), - data_contract: self.clone(), - }, + DataContractError::InvalidDocumentTypeError(InvalidDocumentTypeError::new( + doc_type.to_owned(), + self.id.clone(), + )), )); }; @@ -354,10 +355,10 @@ impl DataContract { ) -> Result<&BTreeMap, ProtocolError> { self.get_optional_binary_properties(doc_type)? .ok_or(ProtocolError::DataContractError( - DataContractError::InvalidDocumentTypeError { - doc_type: doc_type.to_owned(), - data_contract: self.clone(), - }, + DataContractError::InvalidDocumentTypeError(InvalidDocumentTypeError::new( + doc_type.to_owned(), + self.id.clone(), + )), )) } diff --git a/packages/rs-dpp/src/data_contract/data_contract_factory.rs b/packages/rs-dpp/src/data_contract/data_contract_factory.rs index e15c8168696..a3f0baccb07 100644 --- a/packages/rs-dpp/src/data_contract/data_contract_factory.rs +++ b/packages/rs-dpp/src/data_contract/data_contract_factory.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use data_contract::state_transition::property_names as st_prop; +use crate::data_contract::errors::InvalidDataContractError; use crate::data_contract::property_names; use crate::util::serializer::value_to_cbor; use crate::{ @@ -114,10 +115,9 @@ impl DataContractFactory { let result = self.validate_data_contract.validate(&raw_data_contract)?; if !result.is_valid() { - return Err(ProtocolError::InvalidDataContractError { - errors: result.errors, - raw_data_contract, - }); + return Err(ProtocolError::InvalidDataContractError( + InvalidDataContractError::new(result.errors, raw_data_contract), + )); } } DataContract::from_raw_object(raw_data_contract) diff --git a/packages/rs-dpp/src/data_contract/document_type/document_type.rs b/packages/rs-dpp/src/data_contract/document_type/document_type.rs index 92a7c94c99e..b58ffdcbc18 100644 --- a/packages/rs-dpp/src/data_contract/document_type/document_type.rs +++ b/packages/rs-dpp/src/data_contract/document_type/document_type.rs @@ -8,7 +8,6 @@ use super::{ use crate::data_contract::document_type::{property_names, ArrayFieldType}; use crate::data_contract::errors::{DataContractError, StructureError}; -use crate::util::cbor_value::CborBTreeMapHelper; use crate::ProtocolError; use platform_value::btreemap_extensions::BTreeValueMapHelper; use platform_value::Value; diff --git a/packages/rs-dpp/src/data_contract/errors/contract.rs b/packages/rs-dpp/src/data_contract/errors/contract.rs index ec8f3529ea0..670ae1f45b6 100644 --- a/packages/rs-dpp/src/data_contract/errors/contract.rs +++ b/packages/rs-dpp/src/data_contract/errors/contract.rs @@ -1,3 +1,4 @@ +use crate::consensus::basic::document::InvalidDocumentTypeError; use thiserror::Error; use crate::data_contract::DataContract; @@ -14,11 +15,8 @@ pub enum DataContractError { raw_data_contract: DataContract, }, - #[error("Data Contract doesn't define document with type {doc_type}")] - InvalidDocumentTypeError { - doc_type: String, - data_contract: DataContract, - }, + #[error(transparent)] + InvalidDocumentTypeError(InvalidDocumentTypeError), #[error("missing required key: {0}")] MissingRequiredKey(&'static str), diff --git a/packages/rs-dpp/src/data_contract/errors/data_contract_not_present_error.rs b/packages/rs-dpp/src/data_contract/errors/data_contract_not_present_error.rs new file mode 100644 index 00000000000..1e590d832c3 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/errors/data_contract_not_present_error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::identifier::Identifier; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Data Contract is not present")] +pub struct DataContractNotPresentError { + data_contract_id: Identifier, +} + +impl DataContractNotPresentError { + pub fn new(data_contract_id: Identifier) -> Self { + Self { data_contract_id } + } + + pub fn data_contract_id(&self) -> Identifier { + self.data_contract_id.clone() + } +} + +impl From for ProtocolError { + fn from(err: DataContractNotPresentError) -> Self { + Self::DataContractNotPresentError(err) + } +} diff --git a/packages/rs-dpp/src/data_contract/errors/identity_not_present_error.rs b/packages/rs-dpp/src/data_contract/errors/identity_not_present_error.rs new file mode 100644 index 00000000000..1870dbcbb69 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/errors/identity_not_present_error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::identifier::Identifier; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Identity is not present")] +pub struct IdentityNotPresentError { + id: Identifier, +} + +impl IdentityNotPresentError { + pub fn new(id: Identifier) -> Self { + Self { id } + } + + pub fn id(&self) -> Identifier { + self.id.clone() + } +} + +impl From for ProtocolError { + fn from(err: IdentityNotPresentError) -> Self { + Self::IdentityNotPresentError(err) + } +} diff --git a/packages/rs-dpp/src/data_contract/errors/invalid_data_contract_error.rs b/packages/rs-dpp/src/data_contract/errors/invalid_data_contract_error.rs new file mode 100644 index 00000000000..6482309ac96 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/errors/invalid_data_contract_error.rs @@ -0,0 +1,34 @@ +use crate::consensus::ConsensusError; +use thiserror::Error; + +use crate::document::document_transition::document_base_transition::JsonValue; +use crate::ProtocolError; + +#[derive(Error, Debug)] +#[error("Invalid Data Contract: {errors:?}")] +pub struct InvalidDataContractError { + pub errors: Vec, + raw_data_contract: JsonValue, +} + +impl InvalidDataContractError { + pub fn new(errors: Vec, raw_data_contract: JsonValue) -> Self { + Self { + errors, + raw_data_contract, + } + } + + pub fn errors(&self) -> &[ConsensusError] { + &self.errors + } + pub fn raw_data_contract(&self) -> JsonValue { + self.raw_data_contract.clone() + } +} + +impl From for ProtocolError { + fn from(err: InvalidDataContractError) -> Self { + Self::InvalidDataContractError(err) + } +} diff --git a/packages/rs-dpp/src/data_contract/errors/invalid_document_type_error.rs b/packages/rs-dpp/src/data_contract/errors/invalid_document_type_error.rs new file mode 100644 index 00000000000..8f63b56ea7a --- /dev/null +++ b/packages/rs-dpp/src/data_contract/errors/invalid_document_type_error.rs @@ -0,0 +1,33 @@ +use thiserror::Error; + +use crate::data_contract::DataContract; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq)] +#[error("Data Contract doesn't define document with type {doc_type}")] +pub struct InvalidDocumentTypeError { + doc_type: String, + data_contract: DataContract, +} + +impl InvalidDocumentTypeError { + pub fn new(doc_type: String, data_contract: DataContract) -> Self { + Self { + doc_type, + data_contract, + } + } + + pub fn doc_type(&self) -> String { + self.doc_type.clone() + } + pub fn data_contract(&self) -> DataContract { + self.data_contract.clone() + } +} + +impl From for ProtocolError { + fn from(err: InvalidDocumentTypeError) -> Self { + Self::InvalidDocumentTypeError(err) + } +} diff --git a/packages/rs-dpp/src/data_contract/errors/mod.rs b/packages/rs-dpp/src/data_contract/errors/mod.rs index 89a3e42ffc7..9cdd4235b5f 100644 --- a/packages/rs-dpp/src/data_contract/errors/mod.rs +++ b/packages/rs-dpp/src/data_contract/errors/mod.rs @@ -1,5 +1,13 @@ mod contract; +mod data_contract_not_present_error; +mod identity_not_present_error; +mod invalid_data_contract_error; +mod invalid_document_type_error; mod structure; pub use contract::DataContractError; +pub use data_contract_not_present_error::*; +pub use identity_not_present_error::*; +pub use invalid_data_contract_error::*; +pub use invalid_document_type_error::*; pub use structure::StructureError; diff --git a/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/validation/state/validate_data_contract_create_transition_basic.rs b/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/validation/state/validate_data_contract_create_transition_basic.rs index e96b6145bd5..3b9942153e4 100644 --- a/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/validation/state/validate_data_contract_create_transition_basic.rs +++ b/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/validation/state/validate_data_contract_create_transition_basic.rs @@ -5,6 +5,8 @@ use anyhow::anyhow; use lazy_static::lazy_static; use serde_json::Value; +use crate::consensus::basic::data_contract::InvalidDataContractIdError; +use crate::consensus::basic::decode::ProtocolVersionParsingError; use crate::{ consensus::{basic::BasicError, ConsensusError}, data_contract::{generate_data_contract_id, state_transition::property_names}, @@ -16,7 +18,6 @@ use crate::{ util::json_value::JsonValueExt, validation::{ DataValidator, DataValidatorWithContext, JsonSchemaValidator, SimpleValidationResult, - ValidationResult, }, version::ProtocolVersionValidator, ProtocolError, @@ -87,7 +88,9 @@ fn validate_data_contract_create_transition_basic( Ok(v) => v, Err(parsing_error) => { return Ok(SimpleValidationResult::new(Some(vec![ - ConsensusError::ProtocolVersionParsingError { parsing_error }, + ConsensusError::ProtocolVersionParsingError(ProtocolVersionParsingError::new( + parsing_error, + )), ]))) } }; @@ -113,10 +116,9 @@ fn validate_data_contract_create_transition_basic( let mut validation_result = SimpleValidationResult::default(); if generated_id != raw_data_contract_id { - validation_result.add_error(BasicError::InvalidDataContractIdError { - expected_id: generated_id, - invalid_id: raw_data_contract_id, - }) + validation_result.add_error(BasicError::InvalidDataContractIdError( + InvalidDataContractIdError::new(generated_id, raw_data_contract_id), + )) } Ok(validation_result) diff --git a/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic.rs b/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic.rs index 954cb624b25..e7a37e4b683 100644 --- a/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic.rs +++ b/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic.rs @@ -1,12 +1,12 @@ use std::convert::{TryFrom, TryInto}; -use anyhow::anyhow; -use anyhow::Context; -use json_patch::PatchOperation; -use lazy_static::lazy_static; -use serde_json::{json, Value as JsonValue}; -use std::sync::Arc; - +use crate::consensus::basic::data_contract::{ + DataContractImmutablePropertiesUpdateError, IncompatibleDataContractSchemaError, +}; +use crate::consensus::basic::decode::ProtocolVersionParsingError; +use crate::consensus::basic::invalid_data_contract_version_error::InvalidDataContractVersionError; +use crate::consensus::ConsensusError; +use crate::state_transition::state_transition_execution_context::StateTransitionExecutionContext; use crate::{ consensus::basic::BasicError, data_contract::{ @@ -20,10 +20,12 @@ use crate::{ version::ProtocolVersionValidator, DashPlatformProtocolInitError, ProtocolError, }; -use crate::{ - consensus::ConsensusError, - state_transition::state_transition_execution_context::StateTransitionExecutionContext, -}; +use anyhow::anyhow; +use anyhow::Context; +use json_patch::PatchOperation; +use lazy_static::lazy_static; +use serde_json::{json, Value as JsonValue}; +use std::sync::Arc; use super::schema_compatibility_validator::validate_schema_compatibility; use super::schema_compatibility_validator::DiffVAlidatorError; @@ -83,7 +85,9 @@ where Ok(v) => v, Err(parsing_error) => { return Ok(SimpleValidationResult::new(Some(vec![ - ConsensusError::ProtocolVersionParsingError { parsing_error }, + ConsensusError::ProtocolVersionParsingError(ProtocolVersionParsingError::new( + parsing_error, + )), ]))) } }; @@ -127,10 +131,9 @@ where let new_version = raw_data_contract.get_u64(contract_property_names::VERSION)? as u32; let old_version = existing_data_contract.version; if (new_version - old_version) != 1 { - validation_result.add_error(BasicError::InvalidDataContractVersionError { - expected_version: old_version + 1, - version: new_version, - }) + validation_result.add_error(BasicError::InvalidDataContractVersionError( + InvalidDataContractVersionError::new(old_version + 1, new_version), + )) } let raw_existing_data_contract = existing_data_contract.to_object(false)?; @@ -170,10 +173,12 @@ where for diff in base_data_contract_diff.0.iter() { let (operation, property_name) = get_operation_and_property_name(diff); - validation_result.add_error(BasicError::DataContractImmutablePropertiesUpdateError { - operation: operation.to_owned(), - field_path: property_name.to_owned(), - }) + validation_result.add_error(BasicError::DataContractImmutablePropertiesUpdateError( + DataContractImmutablePropertiesUpdateError::new( + operation.to_owned(), + property_name.to_owned(), + ), + )) } if !validation_result.is_valid() { return Ok(validation_result); @@ -191,13 +196,15 @@ where Err(DiffVAlidatorError::SchemaCompatibilityError { diffs }) => { let (operation_name, property_name) = get_operation_and_property_name(&diffs[0]); - validation_result.add_error(BasicError::IncompatibleDataContractSchemaError { - data_contract_id: existing_data_contract.id, - operation: operation_name.to_owned(), - field_path: property_name.to_owned(), - old_schema: document_schema.clone(), - new_schema: new_document_schema.clone(), - }); + validation_result.add_error(BasicError::IncompatibleDataContractSchemaError( + IncompatibleDataContractSchemaError::new( + existing_data_contract.id.clone(), + operation_name.to_owned(), + property_name.to_owned(), + document_schema.clone(), + new_document_schema.clone(), + ), + )); } Err(DiffVAlidatorError::DataStructureError(e)) => { return Err(ProtocolError::ParsingError(e.to_string())) diff --git a/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible.rs b/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible.rs index 6e049fcec61..c82de08cb7a 100644 --- a/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible.rs +++ b/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible.rs @@ -1,6 +1,10 @@ use std::collections::HashSet; use std::collections::{BTreeMap, HashMap}; +use crate::consensus::basic::data_contract::{ + DataContractHaveNewUniqueIndexError, DataContractInvalidIndexDefinitionUpdateError, + DataContractUniqueIndicesChangedError, +}; use crate::consensus::basic::BasicError; use crate::data_contract::document_type::IndexProperty; use crate::util::json_schema::Index; @@ -65,10 +69,12 @@ pub fn validate_indices_are_backward_compatible<'a>( let maybe_changed_unique_existing_index = get_changed_old_unique_index(&existing_schema_indices, &name_new_index_map); if let Some(changed_index) = maybe_changed_unique_existing_index { - result.add_error(BasicError::DataContractUniqueIndicesChangedError { - document_type: document_type.to_owned(), - index_name: changed_index.name.clone(), - }); + result.add_error(BasicError::DataContractUniqueIndicesChangedError( + DataContractUniqueIndicesChangedError::new( + document_type.to_owned(), + changed_index.name.clone(), + ), + )); } let maybe_wrongly_updated_index = get_wrongly_updated_non_unique_index( @@ -77,19 +83,23 @@ pub fn validate_indices_are_backward_compatible<'a>( existing_schema, )?; if let Some(index) = maybe_wrongly_updated_index { - result.add_error(BasicError::DataContractInvalidIndexDefinitionUpdateError { - document_type: document_type.to_owned(), - index_name: index.name.clone(), - }) + result.add_error(BasicError::DataContractInvalidIndexDefinitionUpdateError( + DataContractInvalidIndexDefinitionUpdateError::new( + document_type.to_owned(), + index.name.clone(), + ), + )) } let maybe_new_unique_index = get_new_unique_index(&existing_schema_indices, name_new_index_map.values())?; if let Some(index) = maybe_new_unique_index { - result.add_error(BasicError::DataContractHaveNewUniqueIndexError { - document_type: document_type.to_owned(), - index_name: index.name.clone(), - }) + result.add_error(BasicError::DataContractHaveNewUniqueIndexError( + DataContractHaveNewUniqueIndexError::new( + document_type.to_owned(), + index.name.clone(), + ), + )) } let maybe_wrongly_constructed_new_index = get_wrongly_constructed_new_index( existing_schema_indices.iter(), @@ -97,10 +107,12 @@ pub fn validate_indices_are_backward_compatible<'a>( added_properties.copied(), )?; if let Some(index) = maybe_wrongly_constructed_new_index { - result.add_error(BasicError::DataContractInvalidIndexDefinitionUpdateError { - document_type: document_type.to_owned(), - index_name: index.name.clone(), - }) + result.add_error(BasicError::DataContractInvalidIndexDefinitionUpdateError( + DataContractInvalidIndexDefinitionUpdateError::new( + document_type.to_owned(), + index.name.clone(), + ), + )) } } diff --git a/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/state/validate_data_contract_update_transition_state.rs b/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/state/validate_data_contract_update_transition_state.rs index ceb956cbc9f..56f96f72374 100644 --- a/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/state/validate_data_contract_update_transition_state.rs +++ b/packages/rs-dpp/src/data_contract/state_transition/data_contract_update_transition/validation/state/validate_data_contract_update_transition_state.rs @@ -3,6 +3,7 @@ use std::convert::TryInto; use anyhow::Result; use async_trait::async_trait; +use crate::consensus::basic::invalid_data_contract_version_error::InvalidDataContractVersionError; use crate::{ data_contract::{state_transition::DataContractUpdateTransition, DataContract}, errors::consensus::basic::BasicError, @@ -80,10 +81,9 @@ pub async fn validate_data_contract_update_transition_state( let new_version = state_transition.data_contract.version; if new_version < old_version || new_version - old_version != 1 { - let err = BasicError::InvalidDataContractVersionError { - expected_version: old_version + 1, - version: new_version, - }; + let err = BasicError::InvalidDataContractVersionError( + InvalidDataContractVersionError::new(old_version + 1, new_version), + ); result.add_error(err); } diff --git a/packages/rs-dpp/src/data_contract/state_transition/errors/missing_data_contract_id_error.rs b/packages/rs-dpp/src/data_contract/state_transition/errors/missing_data_contract_id_error.rs new file mode 100644 index 00000000000..1962ea3c8bd --- /dev/null +++ b/packages/rs-dpp/src/data_contract/state_transition/errors/missing_data_contract_id_error.rs @@ -0,0 +1,28 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::document::document_transition::document_base_transition::JsonValue; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("$dataContractId is not present")] +pub struct MissingDataContractIdError { + raw_document_transition: JsonValue, +} + +impl MissingDataContractIdError { + pub fn new(raw_document_transition: JsonValue) -> Self { + Self { + raw_document_transition, + } + } + + pub fn raw_document_transition(&self) -> JsonValue { + self.raw_document_transition.clone() + } +} + +impl From for BasicError { + fn from(err: MissingDataContractIdError) -> Self { + Self::MissingDataContractIdError(err) + } +} diff --git a/packages/rs-dpp/src/data_contract/state_transition/errors/mod.rs b/packages/rs-dpp/src/data_contract/state_transition/errors/mod.rs new file mode 100644 index 00000000000..61ac29290ae --- /dev/null +++ b/packages/rs-dpp/src/data_contract/state_transition/errors/mod.rs @@ -0,0 +1,5 @@ +mod missing_data_contract_id_error; +mod public_key_is_disabled_error; + +pub use missing_data_contract_id_error::*; +pub use public_key_is_disabled_error::*; diff --git a/packages/rs-dpp/src/data_contract/state_transition/errors/public_key_is_disabled_error.rs b/packages/rs-dpp/src/data_contract/state_transition/errors/public_key_is_disabled_error.rs new file mode 100644 index 00000000000..f0e63ce7479 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/state_transition/errors/public_key_is_disabled_error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::identity::IdentityPublicKey; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Public key is disabled")] +pub struct PublicKeyIsDisabledError { + public_key: IdentityPublicKey, +} + +impl PublicKeyIsDisabledError { + pub fn new(public_key: IdentityPublicKey) -> Self { + Self { public_key } + } + + pub fn public_key(&self) -> IdentityPublicKey { + self.public_key.clone() + } +} + +impl From for ProtocolError { + fn from(err: PublicKeyIsDisabledError) -> Self { + Self::PublicKeyIsDisabledError(err) + } +} diff --git a/packages/rs-dpp/src/data_contract/state_transition/mod.rs b/packages/rs-dpp/src/data_contract/state_transition/mod.rs index 6b75a4d569b..a08c435e710 100644 --- a/packages/rs-dpp/src/data_contract/state_transition/mod.rs +++ b/packages/rs-dpp/src/data_contract/state_transition/mod.rs @@ -3,6 +3,7 @@ pub use data_contract_update_transition::*; pub mod data_contract_create_transition; pub mod data_contract_update_transition; +pub mod errors; pub(crate) mod property_names { pub const SIGNATURE_PUBLIC_KEY_ID: &str = "signaturePublicKeyId"; diff --git a/packages/rs-dpp/src/data_contract/validation/data_contract_validator.rs b/packages/rs-dpp/src/data_contract/validation/data_contract_validator.rs index 0e72de70702..6c011e1a3f6 100644 --- a/packages/rs-dpp/src/data_contract/validation/data_contract_validator.rs +++ b/packages/rs-dpp/src/data_contract/validation/data_contract_validator.rs @@ -6,6 +6,12 @@ use lazy_static::lazy_static; use log::trace; use serde_json::Value as JsonValue; +use crate::consensus::basic::data_contract::{ + DuplicateIndexError, DuplicateIndexNameError, InvalidCompoundIndexError, + InvalidIndexPropertyTypeError, InvalidIndexedPropertyConstraintError, + SystemPropertyIndexAlreadyPresentError, UndefinedIndexPropertyError, + UniqueIndicesLimitReachedError, +}; use crate::{ consensus::basic::{BasicError, IndexError}, data_contract::{ @@ -230,10 +236,10 @@ fn validate_index_definitions( if !all_are_required && !all_are_not_required { result.add_error(BasicError::IndexError( - IndexError::InvalidCompoundIndexError { - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - }, + IndexError::InvalidCompoundIndexError(InvalidCompoundIndexError::new( + document_type.to_owned(), + index_definition.clone(), + )), )); } @@ -241,10 +247,9 @@ fn validate_index_definitions( let indices_fingerprint = serde_json::to_string(&index_definition.properties) .expect("fingerprint creation shouldn't fail"); if indices_fingerprints.contains(&indices_fingerprint) { - result.add_error(BasicError::IndexError(IndexError::DuplicateIndexError { - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - })); + result.add_error(BasicError::IndexError(IndexError::DuplicateIndexError( + DuplicateIndexError::new(document_type.to_owned(), index_definition.clone()), + ))); } indices_fingerprints.push(indices_fingerprint) } @@ -289,12 +294,12 @@ fn validate_property_definition( if !invalid_property_type.is_empty() { result.add_error(BasicError::IndexError( - IndexError::InvalidIndexPropertyTypeError { - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - property_name: property_name.to_owned(), - property_type: invalid_property_type.clone(), - }, + IndexError::InvalidIndexPropertyTypeError(InvalidIndexPropertyTypeError::new( + document_type.to_owned(), + index_definition.clone(), + property_name.to_owned(), + invalid_property_type.clone(), + )), )); } @@ -336,13 +341,15 @@ fn validate_property_definition( if max_items.is_none() || max_items.unwrap() > max_limit as u64 { result.add_error(BasicError::IndexError( - IndexError::InvalidIndexedPropertyConstraintError { - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - property_name: property_name.to_owned(), - constraint_name: String::from("maxItems"), - reason: format!("should be less or equal {}", max_limit), - }, + IndexError::InvalidIndexedPropertyConstraintError( + InvalidIndexedPropertyConstraintError::new( + document_type.to_owned(), + index_definition.clone(), + property_name.to_owned(), + String::from("maxItems"), + format!("should be less or equal {}", max_limit), + ), + ), )); } } @@ -352,16 +359,18 @@ fn validate_property_definition( if max_length.is_none() || max_length.unwrap() > MAX_INDEXED_STRING_PROPERTY_LENGTH as u64 { result.add_error(BasicError::IndexError( - IndexError::InvalidIndexedPropertyConstraintError { - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - property_name: property_name.to_owned(), - constraint_name: String::from("maxLength"), - reason: format!( - "should be less or equal than {}", - MAX_INDEXED_STRING_PROPERTY_LENGTH + IndexError::InvalidIndexedPropertyConstraintError( + InvalidIndexedPropertyConstraintError::new( + document_type.to_owned(), + index_definition.clone(), + property_name.to_owned(), + String::from("maxLength"), + format!( + "should be less or equal than {}", + MAX_INDEXED_STRING_PROPERTY_LENGTH + ), ), - }, + ), )) } } @@ -379,11 +388,11 @@ fn validate_not_defined_properties( for (property_name, definition) in properties { if definition.is_none() { result.add_error(BasicError::IndexError( - IndexError::UndefinedIndexPropertyError { - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - property_name: property_name.to_owned().to_owned(), - }, + IndexError::UndefinedIndexPropertyError(UndefinedIndexPropertyError::new( + document_type.to_owned(), + index_definition.clone(), + property_name.to_owned().to_owned(), + )), )) } } @@ -397,10 +406,9 @@ fn validate_index_naming_duplicates( ) -> ValidationResult<()> { let mut result = ValidationResult::default(); for duplicate_index in indices.iter().map(|i| &i.name).duplicates() { - result.add_error(BasicError::DuplicateIndexNameError { - document_type: document_type.to_owned(), - duplicate_index_name: duplicate_index.to_owned(), - }) + result.add_error(BasicError::DuplicateIndexNameError( + DuplicateIndexNameError::new(document_type.to_owned(), duplicate_index.to_owned()), + )) } result } @@ -410,10 +418,10 @@ fn validate_max_unique_indices(indices: &[Index], document_type: &str) -> Valida let mut result = ValidationResult::default(); if indices.iter().filter(|i| i.unique).count() > UNIQUE_INDEX_LIMIT { result.add_error(BasicError::IndexError( - IndexError::UniqueIndicesLimitReachedError { - document_type: document_type.to_owned(), - index_limit: UNIQUE_INDEX_LIMIT, - }, + IndexError::UniqueIndicesLimitReachedError(UniqueIndicesLimitReachedError::new( + document_type.to_owned(), + UNIQUE_INDEX_LIMIT, + )), )) } @@ -430,11 +438,13 @@ fn validate_no_system_indices( for property in index_definition.properties.iter() { if NOT_ALLOWED_SYSTEM_PROPERTIES.contains(&property.name.as_str()) { result.add_error(BasicError::IndexError( - IndexError::SystemPropertyIndexAlreadyPresentError { - property_name: property.name.to_owned(), - document_type: document_type.to_owned(), - index_definition: index_definition.clone(), - }, + IndexError::SystemPropertyIndexAlreadyPresentError( + SystemPropertyIndexAlreadyPresentError::new( + document_type.to_owned(), + index_definition.clone(), + property.name.to_owned(), + ), + ), )); } } diff --git a/packages/rs-dpp/src/data_contract/validation/multi_validator.rs b/packages/rs-dpp/src/data_contract/validation/multi_validator.rs index 5d864cf305e..c0584ac25d1 100644 --- a/packages/rs-dpp/src/data_contract/validation/multi_validator.rs +++ b/packages/rs-dpp/src/data_contract/validation/multi_validator.rs @@ -1,6 +1,7 @@ use regex::Regex; use serde_json::Value as JsonValue; +use crate::consensus::basic::data_contract::IncompatibleRe2PatternError; use crate::{ consensus::{basic::BasicError, ConsensusError}, validation::ValidationResult, @@ -58,11 +59,13 @@ pub fn pattern_is_valid_regex_validator( if key == "pattern" { if let Some(pattern) = value.as_str() { if let Err(err) = Regex::new(pattern) { - result.add_error(ConsensusError::IncompatibleRe2PatternError { - pattern: String::from(pattern), - path: path.to_string(), - message: err.to_string(), - }); + result.add_error(ConsensusError::IncompatibleRe2PatternError( + IncompatibleRe2PatternError::new( + String::from(pattern), + path.to_string(), + err.to_string(), + ), + )); } } } @@ -169,13 +172,17 @@ mod test { let result = validate(&schema, &[pattern_is_valid_regex_validator]); let consensus_error = result.errors.get(0).expect("the error should be returned"); - assert!( - matches!(consensus_error, ConsensusError::IncompatibleRe2PatternError {pattern, path, ..} - if path == "/properties/bar" && - pattern == "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$" && - consensus_error.code() == 1009 - ) - ); + match consensus_error { + ConsensusError::IncompatibleRe2PatternError(err) => { + assert_eq!(err.path(), "/properties/bar".to_string()); + assert_eq!( + err.pattern(), + "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$".to_string() + ); + assert_eq!(consensus_error.code(), 1009); + } + _ => panic!("Expected error to be IncompatibleRe2PatternError"), + } } #[test] @@ -193,13 +200,20 @@ mod test { let result = validate(&schema, &[pattern_is_valid_regex_validator]); let consensus_error = result.errors.get(0).expect("the error should be returned"); - assert!( - matches!(consensus_error, ConsensusError::IncompatibleRe2PatternError {pattern, path, ..} - if path == "/properties/arrayOfObject/items/properties/simple" && - pattern == "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$" && - consensus_error.code() == 1009 - ) - ); + match consensus_error { + ConsensusError::IncompatibleRe2PatternError(err) => { + assert_eq!( + err.path(), + "/properties/arrayOfObject/items/properties/simple".to_string() + ); + assert_eq!( + err.pattern(), + "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$".to_string() + ); + assert_eq!(consensus_error.code(), 1009); + } + _ => panic!("Expected error to be IncompatibleRe2PatternError"), + } } #[test] @@ -211,13 +225,20 @@ mod test { let result = validate(&schema, &[pattern_is_valid_regex_validator]); let consensus_error = result.errors.get(0).expect("the error should be returned"); - assert!( - matches!(consensus_error, ConsensusError::IncompatibleRe2PatternError {pattern, path, ..} - if path == "/properties/arrayOfObjects/items/[0]/properties/simple" && - pattern == "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$" && - consensus_error.code() == 1009 - ) - ); + match consensus_error { + ConsensusError::IncompatibleRe2PatternError(err) => { + assert_eq!( + err.path(), + "/properties/arrayOfObjects/items/[0]/properties/simple".to_string() + ); + assert_eq!( + err.pattern(), + "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$".to_string() + ); + assert_eq!(consensus_error.code(), 1009); + } + _ => panic!("Expected error to be IncompatibleRe2PatternError"), + } } fn get_document_schema() -> JsonValue { diff --git a/packages/rs-dpp/src/data_contract/validation/validate_data_contract_max_depth.rs b/packages/rs-dpp/src/data_contract/validation/validate_data_contract_max_depth.rs index 1e6a5b27ce0..9784faa9a0d 100644 --- a/packages/rs-dpp/src/data_contract/validation/validate_data_contract_max_depth.rs +++ b/packages/rs-dpp/src/data_contract/validation/validate_data_contract_max_depth.rs @@ -3,6 +3,7 @@ use std::collections::BTreeSet; use anyhow::bail; use serde_json::Value as JsonValue; +use crate::consensus::basic::data_contract::InvalidJsonSchemaRefError; use crate::{ consensus::basic::BasicError, util::json_value::JsonValueExt, validation::ValidationResult, }; @@ -42,15 +43,21 @@ fn calc_max_depth(json_value: &JsonValue) -> Result { if property_name == "$ref" { if let Some(uri) = v.as_str() { let resolved = resolve_uri(json_value, uri).map_err(|e| { - BasicError::InvalidJsonSchemaRefError { - ref_error: format!("invalid ref '{}': {}", uri, e), - } + BasicError::InvalidJsonSchemaRefError( + InvalidJsonSchemaRefError::new(format!( + "invalid ref '{}': {}", + uri, e + )), + ) })?; if visited.contains(&(resolved as *const JsonValue)) { - return Err(BasicError::InvalidJsonSchemaRefError { - ref_error: format!("the ref '{}' contains cycles", uri), - }); + return Err(BasicError::InvalidJsonSchemaRefError( + InvalidJsonSchemaRefError::new(format!( + "the ref '{}' contains cycles", + uri + )), + )); } visited.insert(resolved as *const JsonValue); @@ -125,10 +132,12 @@ mod test { } ); let result = calc_max_depth(&schema); - assert!(matches!( - result, - Err(BasicError::InvalidJsonSchemaRefError { ref_error }) if ref_error == "the ref '#/$defs/object' contains cycles" - )); + + let err = get_ref_error(result); + assert_eq!( + err.ref_error(), + "the ref '#/$defs/object' contains cycles".to_string() + ); } #[test] @@ -181,11 +190,14 @@ mod test { } ); let result = calc_max_depth(&schema); - println!("the result is {:#?}", result); - assert!(matches!( - result, - Err(BasicError::InvalidJsonSchemaRefError { ref_error }) if ref_error.starts_with("invalid ref '#/$defs/object'") - )); + + let err = get_ref_error(result); + assert!(err.ref_error().starts_with("invalid ref '#/$defs/object'")); + // println!("the result is {:#?}", result); + // assert!(matches!( + // result, + // Err(BasicError::InvalidJsonSchemaRefError { ref_error }) if ref_error.starts_with("invalid ref '#/$defs/object'") + // )); } #[test] @@ -208,10 +220,18 @@ mod test { } ); let result = calc_max_depth(&schema); - assert!(matches!( - result, - Err(BasicError::InvalidJsonSchemaRefError { ref_error }) if ref_error == "invalid ref 'https://json-schema.org/some': only local references are allowed" - )); + + let err = get_ref_error(result); + assert_eq!( + err.ref_error(), + "invalid ref 'https://json-schema.org/some': only local references are allowed" + .to_string() + ); + + // assert!(matches!( + // result, + // Err(BasicError::InvalidJsonSchemaRefError { ref_error }) if ref_error == "invalid ref 'https://json-schema.org/some': only local references are allowed" + // )); } #[test] @@ -234,10 +254,12 @@ mod test { } ); let result = calc_max_depth(&schema); - assert!(matches!( - result, - Err(BasicError::InvalidJsonSchemaRefError { ref_error }) if ref_error == "invalid ref '': only local references are allowed" - )); + + let err = get_ref_error(result); + assert_eq!( + err.ref_error(), + "invalid ref '': only local references are allowed".to_string() + ); } #[test] @@ -281,4 +303,14 @@ mod test { }); assert!(matches!(calc_max_depth(&schema), Ok(4))); } + + pub fn get_ref_error(result: Result) -> InvalidJsonSchemaRefError { + match result { + Ok(_) => panic!("expected to have validation error"), + Err(e) => match e { + BasicError::InvalidJsonSchemaRefError(err) => err, + _ => panic!("expected error to be a InvalidJsonSchemaRefError"), + }, + } + } } diff --git a/packages/rs-dpp/src/document/document_factory.rs b/packages/rs-dpp/src/document/document_factory.rs index 3ab5b588701..6ff48f4dec2 100644 --- a/packages/rs-dpp/src/document/document_factory.rs +++ b/packages/rs-dpp/src/document/document_factory.rs @@ -4,6 +4,7 @@ use itertools::Itertools; use serde::{Deserialize, Serialize}; use serde_json::{json, Value as JsonValue}; +use crate::consensus::basic::document::InvalidDocumentTypeError; use crate::{ data_contract::{errors::DataContractError, DataContract}, decode_protocol_entity_factory::DecodeProtocolEntity, @@ -95,10 +96,9 @@ where data: JsonValue, ) -> Result { if !data_contract.is_document_defined(&document_type) { - return Err(DataContractError::InvalidDocumentTypeError { - doc_type: document_type, - data_contract, - } + return Err(DataContractError::InvalidDocumentTypeError( + InvalidDocumentTypeError::new(document_type, data_contract.id), + ) .into()); } diff --git a/packages/rs-dpp/src/document/document_stub.rs b/packages/rs-dpp/src/document/document_stub.rs index e3742906deb..d060cfdee10 100644 --- a/packages/rs-dpp/src/document/document_stub.rs +++ b/packages/rs-dpp/src/document/document_stub.rs @@ -54,7 +54,6 @@ use crate::ProtocolError; use crate::document::document_transition::INITIAL_REVISION; use crate::document::property_names; use crate::prelude::*; -use crate::util::cbor_value::CborBTreeMapHelper; use anyhow::{anyhow, bail}; use platform_value::btreemap_extensions::BTreeValueMapHelper; use platform_value::Value; diff --git a/packages/rs-dpp/src/document/document_validator.rs b/packages/rs-dpp/src/document/document_validator.rs index 4b3b0232a33..68bf2340b0e 100644 --- a/packages/rs-dpp/src/document/document_validator.rs +++ b/packages/rs-dpp/src/document/document_validator.rs @@ -4,6 +4,7 @@ use anyhow::anyhow; use lazy_static::lazy_static; use serde_json::Value as JsonValue; +use crate::consensus::basic::document::InvalidDocumentTypeError; use crate::{ consensus::basic::BasicError, data_contract::{ @@ -57,10 +58,12 @@ impl DocumentValidator { })?; if !data_contract.is_document_defined(document_type) { - result.add_error(BasicError::InvalidDocumentTypeError { - document_type: document_type.to_owned(), - data_contract_id: data_contract.id.to_owned(), - }); + result.add_error(BasicError::InvalidDocumentTypeError( + InvalidDocumentTypeError::new( + document_type.to_owned(), + data_contract.id.to_owned(), + ), + )); return Ok(result); } diff --git a/packages/rs-dpp/src/document/fetch_and_validate_data_contract.rs b/packages/rs-dpp/src/document/fetch_and_validate_data_contract.rs index ba93db0e525..89aedc4df0c 100644 --- a/packages/rs-dpp/src/document/fetch_and_validate_data_contract.rs +++ b/packages/rs-dpp/src/document/fetch_and_validate_data_contract.rs @@ -2,6 +2,8 @@ use std::{convert::TryInto, sync::Arc}; use serde_json::Value; +use crate::consensus::basic::invalid_identifier_error::InvalidIdentifierError; +use crate::data_contract::state_transition::errors::MissingDataContractIdError; use crate::{ consensus::{basic::BasicError, ConsensusError}, data_contract::DataContract, @@ -57,7 +59,9 @@ pub async fn fetch_and_validate_data_contract( id_bytes } else { validation_result.add_error(ConsensusError::BasicError(Box::new( - BasicError::MissingDataContractIdError, + BasicError::MissingDataContractIdError(MissingDataContractIdError::new( + raw_document.clone(), + )), ))); return Ok(validation_result); }; @@ -68,10 +72,9 @@ pub async fn fetch_and_validate_data_contract( Err(e) => { let id_base58 = bs58::encode(id_bytes).into_string(); let consensus_error = - ConsensusError::BasicError(Box::new(BasicError::InvalidIdentifierError { - identifier_name: id_base58, - error: e.to_string(), - })); + ConsensusError::BasicError(Box::new(BasicError::InvalidIdentifierError( + InvalidIdentifierError::new(id_base58, e.to_string()), + ))); validation_result.add_error(consensus_error); return Ok(validation_result); } diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_documents_batch_transition_basic.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_documents_batch_transition_basic.rs index 6d4204bd348..dc9a9946428 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_documents_batch_transition_basic.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_documents_batch_transition_basic.rs @@ -3,6 +3,13 @@ use std::{ convert::{TryFrom, TryInto}, }; +use crate::consensus::basic::document::{ + DuplicateDocumentTransitionsWithIdsError, DuplicateDocumentTransitionsWithIndicesError, + InvalidDocumentTransitionActionError, InvalidDocumentTransitionIdError, + InvalidDocumentTypeError, +}; +use crate::consensus::basic::invalid_identifier_error::InvalidIdentifierError; +use crate::data_contract::state_transition::errors::MissingDataContractIdError; use crate::document::validation::basic::find_duplicates_by_id::find_duplicates_by_id; use crate::{ consensus::basic::BasicError, @@ -92,7 +99,9 @@ pub async fn validate_documents_batch_transition_basic( for raw_document_transition in raw_document_transitions { let data_contract_id_bytes = match raw_document_transition.get_bytes("$dataContractId") { Err(_) => { - result.add_error(BasicError::MissingDataContractIdError); + result.add_error(BasicError::MissingDataContractIdError( + MissingDataContractIdError::new(raw_document_transition.clone()), + )); continue; } Ok(id) => id, @@ -101,10 +110,9 @@ pub async fn validate_documents_batch_transition_basic( let identifier = match Identifier::from_bytes(&data_contract_id_bytes) { Ok(identifier) => identifier, Err(e) => { - result.add_error(BasicError::InvalidIdentifierError { - identifier_name: String::from("$dataContractId"), - error: e.to_string(), - }); + result.add_error(BasicError::InvalidIdentifierError( + InvalidIdentifierError::new(String::from("$dataContractId"), e.to_string()), + )); continue; } }; @@ -214,10 +222,12 @@ fn validate_raw_transitions<'a>( Ok(document_type) => { if !data_contract.is_document_defined(document_type) { - result.add_error(BasicError::InvalidDocumentTypeError { - document_type: document_type.to_string(), - data_contract_id: *data_contract.id(), - }); + result.add_error(BasicError::InvalidDocumentTypeError( + InvalidDocumentTypeError::new( + document_type.to_string(), + data_contract.id().clone(), + ), + )); return Ok(result); } document_type @@ -235,9 +245,9 @@ fn validate_raw_transitions<'a>( let action = match Action::try_from(document_action as u8) { Ok(action) => action, Err(_) => { - result.add_error(BasicError::InvalidDocumentTransitionActionError { - action: document_action.to_string(), - }); + result.add_error(BasicError::InvalidDocumentTransitionActionError( + InvalidDocumentTransitionActionError::new(document_action.to_string()), + )); return Ok(result); } }; @@ -269,10 +279,12 @@ fn validate_raw_transitions<'a>( generate_document_id(data_contract.id(), owner_id, document_type, &entropy); if generated_document_id != document_id { - result.add_error(BasicError::InvalidDocumentTransitionIdError { - expected_id: generated_document_id, - invalid_id: document_id, - }) + result.add_error(BasicError::InvalidDocumentTransitionIdError( + InvalidDocumentTransitionIdError::new( + generated_document_id, + document_id, + ), + )) } } } @@ -301,7 +313,9 @@ fn validate_raw_transitions<'a>( Ok((doc_type, id)) }) .collect::)>, anyhow::Error>>()?; - result.add_error(BasicError::DuplicateDocumentTransitionsWithIdsError { references }); + result.add_error(BasicError::DuplicateDocumentTransitionsWithIdsError( + DuplicateDocumentTransitionsWithIdsError::new(references), + )); } let duplicate_transitions_by_indices = @@ -315,7 +329,9 @@ fn validate_raw_transitions<'a>( Ok((doc_type, id)) }) .collect::)>, anyhow::Error>>()?; - result.add_error(BasicError::DuplicateDocumentTransitionsWithIndicesError { references }); + result.add_error(BasicError::DuplicateDocumentTransitionsWithIndicesError( + DuplicateDocumentTransitionsWithIndicesError::new(references), + )); } let validation_result = validate_partial_compound_indices( diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_partial_compound_indices.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_partial_compound_indices.rs index 36607a32895..a0dfa9b5bfd 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_partial_compound_indices.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/validate_partial_compound_indices.rs @@ -2,6 +2,7 @@ use std::borrow::Borrow; use serde_json::Value as JsonValue; +use crate::consensus::basic::document::InconsistentCompoundIndexDataError; use crate::{ consensus::basic::BasicError, data_contract::DataContract, @@ -48,10 +49,12 @@ pub fn validate_indices( let properties = index.properties.iter().map(|property| &property.name); if !are_all_properties_defined_or_undefined(properties.clone(), raw_transition) { - validation_result.add_error(BasicError::InconsistentCompoundIndexDataError { - index_properties: properties.map(ToOwned::to_owned).collect(), - document_type: document_type.to_string(), - }) + validation_result.add_error(BasicError::InconsistentCompoundIndexDataError( + InconsistentCompoundIndexDataError::new( + properties.map(ToOwned::to_owned).collect(), + document_type.to_string(), + ), + )) } } diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs index 88e42e0e8c9..111c1348f55 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs @@ -3,6 +3,7 @@ use std::convert::TryInto; use futures::future::join_all; use itertools::Itertools; +use crate::data_contract::errors::DataContractNotPresentError; use crate::{ block_time_window::validate_time_in_block_time_window::validate_time_in_block_time_window, consensus::ConsensusError, @@ -77,8 +78,10 @@ pub async fn validate_document_transitions( .map(TryInto::try_into) .transpose() .map_err(Into::into)? - .ok_or(ProtocolError::DataContractNotPresentError { - data_contract_id: *data_contract_id, + .ok_or_else(|| { + ProtocolError::DataContractNotPresentError(DataContractNotPresentError::new( + data_contract_id.clone(), + )) })?; execution_context.add_operations(tmp_execution_context.get_operations()); @@ -214,9 +217,9 @@ fn check_ownership( if &fetched_document.owner_id != owner_id { result.add_error(ConsensusError::StateError(Box::new( StateError::DocumentOwnerIdMismatchError { - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), document_owner_id: owner_id.to_owned(), - existing_document_owner_id: fetched_document.owner_id, + existing_document_owner_id: fetched_document.owner_id.clone(), }, ))); } @@ -243,7 +246,7 @@ fn check_revision( if revision != expected_revision { result.add_error(ConsensusError::StateError(Box::new( StateError::InvalidDocumentRevisionError { - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), current_revision: fetched_document.revision as Revision, }, ))) @@ -263,7 +266,7 @@ fn check_if_document_is_already_present( if maybe_fetched_document.is_some() { result.add_error(ConsensusError::StateError(Box::new( StateError::DocumentAlreadyPresentError { - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), }, ))) } @@ -282,7 +285,7 @@ fn check_if_document_can_be_found( if maybe_fetched_document.is_none() { result.add_error(ConsensusError::StateError(Box::new( StateError::DocumentNotFoundError { - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), }, ))) } @@ -297,7 +300,7 @@ fn check_if_timestamps_are_equal(document_transition: &DocumentTransition) -> Va if created_at.is_some() && updated_at.is_some() && updated_at.unwrap() != created_at.unwrap() { result.add_error(ConsensusError::StateError(Box::new( StateError::DocumentTimestampsMismatchError { - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), }, ))); } @@ -320,7 +323,7 @@ fn check_created_inside_time_window( result.add_error(ConsensusError::StateError(Box::new( StateError::DocumentTimestampWindowViolationError { timestamp_name: String::from("createdAt"), - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), timestamp: created_at as i64, time_window_start: window_validation.time_window_start as i64, time_window_end: window_validation.time_window_end as i64, @@ -345,7 +348,7 @@ fn check_updated_inside_time_window( result.add_error(ConsensusError::StateError(Box::new( StateError::DocumentTimestampWindowViolationError { timestamp_name: String::from("updatedAt"), - document_id: document_transition.base().id, + document_id: document_transition.base().id.clone(), timestamp: updated_at as i64, time_window_start: window_validation.time_window_start as i64, time_window_end: window_validation.time_window_end as i64, diff --git a/packages/rs-dpp/src/errors/codes.rs b/packages/rs-dpp/src/errors/codes.rs index d7db9ded82e..65a6c763704 100644 --- a/packages/rs-dpp/src/errors/codes.rs +++ b/packages/rs-dpp/src/errors/codes.rs @@ -112,7 +112,7 @@ impl ErrorWithCode for BasicError { Self::DuplicateDocumentTransitionsWithIdsError { .. } => 1019, Self::DuplicateDocumentTransitionsWithIndicesError { .. } => 1020, - Self::MissingDataContractIdError => 1025, + Self::MissingDataContractIdError { .. } => 1025, Self::InvalidIdentifierError { .. } => 1006, // Data contract @@ -130,7 +130,6 @@ impl ErrorWithCode for BasicError { Self::DataContractHaveNewUniqueIndexError { .. } => 0, Self::DataContractInvalidIndexDefinitionUpdateError { .. } => 0, Self::IndexError(ref e) => e.get_code(), - Self::IdentityNotFoundError { .. } => 2000, Self::InvalidDataContractIdError { .. } => 1011, // State Transition diff --git a/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs b/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs index af8a271d204..0cf072fa401 100644 --- a/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs +++ b/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs @@ -2,6 +2,8 @@ use jsonschema::ValidationError; use thiserror::Error; use crate::codes::ErrorWithCode; +use crate::consensus::basic::data_contract::IncompatibleRe2PatternError; +use crate::consensus::basic::decode::ProtocolVersionParsingError; use crate::consensus::basic::identity::{ DuplicatedIdentityPublicKeyError, DuplicatedIdentityPublicKeyIdError, IdentityAssetLockProofLockedTransactionMismatchError, @@ -33,41 +35,41 @@ use super::signature::SignatureError; #[derive(Error, Debug)] //#[cfg_attr(test, derive(Clone))] pub enum ConsensusError { - #[error("{0}")] + #[error(transparent)] JsonSchemaError(JsonSchemaError), - #[error("{0}")] + #[error(transparent)] UnsupportedProtocolVersionError(UnsupportedProtocolVersionError), - #[error("{0}")] + #[error(transparent)] IncompatibleProtocolVersionError(IncompatibleProtocolVersionError), - #[error("{0}")] + #[error(transparent)] DuplicatedIdentityPublicKeyBasicIdError(DuplicatedIdentityPublicKeyIdError), - #[error("{0}")] + #[error(transparent)] InvalidIdentityPublicKeyDataError(InvalidIdentityPublicKeyDataError), - #[error("{0}")] + #[error(transparent)] InvalidIdentityPublicKeySecurityLevelError(InvalidIdentityPublicKeySecurityLevelError), - #[error("{0}")] + #[error(transparent)] DuplicatedIdentityPublicKeyBasicError(DuplicatedIdentityPublicKeyError), - #[error("{0}")] + #[error(transparent)] MissingMasterPublicKeyError(MissingMasterPublicKeyError), - #[error("{0}")] + #[error(transparent)] IdentityAssetLockTransactionOutPointAlreadyExistsError( IdentityAssetLockTransactionOutPointAlreadyExistsError, ), - #[error("{0}")] + #[error(transparent)] InvalidIdentityAssetLockTransactionOutputError(InvalidIdentityAssetLockTransactionOutputError), - #[error("{0}")] + #[error(transparent)] InvalidAssetLockTransactionOutputReturnSize(InvalidAssetLockTransactionOutputReturnSizeError), - #[error("{0}")] + #[error(transparent)] IdentityAssetLockTransactionOutputNotFoundError( IdentityAssetLockTransactionOutputNotFoundError, ), - #[error("{0}")] + #[error(transparent)] InvalidIdentityAssetLockTransactionError(InvalidIdentityAssetLockTransactionError), - #[error("{0}")] + #[error(transparent)] InvalidInstantAssetLockProofError(InvalidInstantAssetLockProofError), - #[error("{0}")] + #[error(transparent)] InvalidInstantAssetLockProofSignatureError(InvalidInstantAssetLockProofSignatureError), - #[error("{0}")] + #[error(transparent)] IdentityAssetLockProofLockedTransactionMismatchError( IdentityAssetLockProofLockedTransactionMismatchError, ), @@ -78,12 +80,12 @@ pub enum ConsensusError { #[error(transparent)] InvalidAssetLockProofTransactionHeightError(InvalidAssetLockProofTransactionHeightError), - #[error("{0}")] + #[error(transparent)] InvalidIdentityCreditWithdrawalTransitionCoreFeeError( InvalidIdentityCreditWithdrawalTransitionCoreFeeError, ), - #[error("{0}")] + #[error(transparent)] InvalidIdentityCreditWithdrawalTransitionOutputScriptError( InvalidIdentityCreditWithdrawalTransitionOutputScriptError, ), @@ -102,17 +104,13 @@ pub enum ConsensusError { #[error("Parsing of serialized object failed due to: {parsing_error}")] SerializedObjectParsingError { parsing_error: anyhow::Error }, - #[error("Can't read protocol version from serialized object: {parsing_error}")] - ProtocolVersionParsingError { parsing_error: anyhow::Error }, + #[error(transparent)] + ProtocolVersionParsingError(ProtocolVersionParsingError), - #[error("Pattern '{pattern}' at '{path}' is not not compatible with Re2: {message}")] - IncompatibleRe2PatternError { - pattern: String, - path: String, - message: String, - }, + #[error(transparent)] + IncompatibleRe2PatternError(IncompatibleRe2PatternError), - #[error("{0}")] + #[error(transparent)] IdentityInsufficientBalanceError(IdentityInsufficientBalanceError), #[error(transparent)] @@ -125,7 +123,7 @@ pub enum ConsensusError { FeeError(FeeError), #[cfg(test)] - #[cfg_attr(test, error("{0}"))] + #[cfg_attr(test, error(transparent))] TestConsensusError(TestConsensusError), } diff --git a/packages/rs-dpp/src/errors/consensus/basic/abstract_basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/abstract_basic_error.rs index ca52aa8191a..27884e8b2f3 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/abstract_basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/abstract_basic_error.rs @@ -1,36 +1,48 @@ -use serde_json::Value as JsonValue; use thiserror::Error; -use crate::{identity::KeyID, prelude::*, util::json_schema::Index}; +use crate::consensus::basic::data_contract::{ + DataContractHaveNewUniqueIndexError, DataContractImmutablePropertiesUpdateError, + DataContractInvalidIndexDefinitionUpdateError, DataContractUniqueIndicesChangedError, + DuplicateIndexError, DuplicateIndexNameError, IncompatibleDataContractSchemaError, + InvalidCompoundIndexError, InvalidDataContractIdError, InvalidIndexPropertyTypeError, + InvalidIndexedPropertyConstraintError, InvalidJsonSchemaRefError, + SystemPropertyIndexAlreadyPresentError, UndefinedIndexPropertyError, + UniqueIndicesLimitReachedError, +}; +use crate::consensus::basic::document::{ + DuplicateDocumentTransitionsWithIdsError, DuplicateDocumentTransitionsWithIndicesError, + InconsistentCompoundIndexDataError, InvalidDocumentTransitionActionError, + InvalidDocumentTransitionIdError, InvalidDocumentTypeError, +}; +use crate::consensus::basic::identity::InvalidIdentityKeySignatureError; +use crate::consensus::basic::invalid_data_contract_version_error::InvalidDataContractVersionError; +use crate::consensus::basic::invalid_identifier_error::InvalidIdentifierError; +use crate::consensus::basic::state_transition::{ + InvalidStateTransitionTypeError, StateTransitionMaxSizeExceededError, +}; +use crate::data_contract::state_transition::errors::MissingDataContractIdError; +use crate::prelude::*; #[derive(Error, Debug)] pub enum BasicError { #[error("Data Contract {data_contract_id} is not present")] DataContractNotPresent { data_contract_id: Identifier }, - #[error("Data Contract version must be {expected_version}, go {version}")] - InvalidDataContractVersionError { expected_version: u32, version: u32 }, + #[error(transparent)] + InvalidDataContractVersionError(InvalidDataContractVersionError), #[error("JSON Schema depth is greater than {0}")] DataContractMaxDepthExceedError(usize), // Document - #[error( - "Data Contract {data_contract_id} doesn't define document with the type {document_type}" - )] - InvalidDocumentTypeError { - document_type: String, - data_contract_id: Identifier, - }, + #[error(transparent)] + InvalidDocumentTypeError(InvalidDocumentTypeError), - #[error("Duplicate index name '{duplicate_index_name}' defined in '{document_type}' document")] - DuplicateIndexNameError { - document_type: String, - duplicate_index_name: String, - }, + #[error(transparent)] + DuplicateIndexNameError(DuplicateIndexNameError), - #[error("Invalid JSON Schema $ref: {ref_error}")] - InvalidJsonSchemaRefError { ref_error: String }, + #[error(transparent)] + InvalidJsonSchemaRefError(InvalidJsonSchemaRefError), #[error(transparent)] IndexError(IndexError), @@ -38,14 +50,8 @@ pub enum BasicError { #[error("{0}")] JsonSchemaCompilationError(String), - #[error( - "Unique compound index properties {:?} are partially set for {document_type}", - index_properties - )] - InconsistentCompoundIndexDataError { - index_properties: Vec, - document_type: String, - }, + #[error(transparent)] + InconsistentCompoundIndexDataError(InconsistentCompoundIndexDataError), #[error("$type is not present")] MissingDocumentTransitionTypeError, @@ -56,97 +62,53 @@ pub enum BasicError { #[error("$action is not present")] MissingDocumentTransitionActionError, - #[error("Document transition action {} is not supported", action)] - InvalidDocumentTransitionActionError { action: String }, - - #[error( - "Invalid document transition id {}, expected {}", - invalid_id, - expected_id - )] - InvalidDocumentTransitionIdError { - expected_id: Identifier, - invalid_id: Identifier, - }, - - #[error("Document transitions with duplicate IDs {:?}", references)] - DuplicateDocumentTransitionsWithIdsError { references: Vec<(String, Vec)> }, - - #[error( - "Document transitions with duplicate unique properties: {:?}", - references - )] - DuplicateDocumentTransitionsWithIndicesError { references: Vec<(String, Vec)> }, - - #[error("$dataContractId is not present")] - MissingDataContractIdError, - - #[error("Invalid {}: {}", identifier_name, error)] - InvalidIdentifierError { - identifier_name: String, - error: String, - }, - - #[error("Document with type {document_type} has updated unique index named '{index_name}'. Change of unique indices is not allowed")] - DataContractUniqueIndicesChangedError { - document_type: String, - index_name: String, - }, - - #[error("Document with type {document_type} has badly constructed index '{index_name}'. Existing properties in the indices should be defined in the beginning of it. ")] - DataContractInvalidIndexDefinitionUpdateError { - document_type: String, - index_name: String, - }, - - #[error("Document with type {document_type} has a new unique index named '{index_name}'. Adding unique indices during Data Contract update is not allowed.")] - DataContractHaveNewUniqueIndexError { - document_type: String, - index_name: String, - }, - - #[error("Identity {identity_id} not found")] - IdentityNotFoundError { identity_id: Identifier }, + #[error(transparent)] + InvalidDocumentTransitionActionError(InvalidDocumentTransitionActionError), + + #[error(transparent)] + InvalidDocumentTransitionIdError(InvalidDocumentTransitionIdError), + + #[error(transparent)] + DuplicateDocumentTransitionsWithIdsError(DuplicateDocumentTransitionsWithIdsError), + + #[error(transparent)] + DuplicateDocumentTransitionsWithIndicesError(DuplicateDocumentTransitionsWithIndicesError), + + #[error(transparent)] + MissingDataContractIdError(MissingDataContractIdError), + + #[error(transparent)] + InvalidIdentifierError(InvalidIdentifierError), + + #[error(transparent)] + DataContractUniqueIndicesChangedError(DataContractUniqueIndicesChangedError), + + #[error(transparent)] + DataContractInvalidIndexDefinitionUpdateError(DataContractInvalidIndexDefinitionUpdateError), + + #[error(transparent)] + DataContractHaveNewUniqueIndexError(DataContractHaveNewUniqueIndexError), #[error("State transition type is not present")] MissingStateTransitionTypeError, - #[error("Invalid State Transition type {transition_type}")] - InvalidStateTransitionTypeError { transition_type: u8 }, - - #[error( - "State transition size {actual_size_kbytes} KB is more than maximum {max_size_kbytes} KB" - )] - StateTransitionMaxSizeExceededError { - actual_size_kbytes: usize, - max_size_kbytes: usize, - }, - - #[error("Only $defs, version and documents fields are allowed to be updated. Forbidden operation '{operation}' on '{field_path}'")] - DataContractImmutablePropertiesUpdateError { - operation: String, - field_path: String, - }, - - #[error( - "Data Contract updated schema is not backward compatible with one defined in Data Contract wid id {data_contract_id}. Field: '{field_path}', Operation: '{operation}'" - )] - IncompatibleDataContractSchemaError { - data_contract_id: Identifier, - operation: String, - field_path: String, - old_schema: JsonValue, - new_schema: JsonValue, - }, - - #[error("Identity key {public_key_id} has invalid signature")] - InvalidIdentityKeySignatureError { public_key_id: KeyID }, - - #[error("Data Contract Id must be {}, got {}", bs58::encode(expected_id).into_string(), bs58::encode(invalid_id).into_string())] - InvalidDataContractIdError { - expected_id: Vec, - invalid_id: Vec, - }, + #[error(transparent)] + InvalidStateTransitionTypeError(InvalidStateTransitionTypeError), + + #[error(transparent)] + StateTransitionMaxSizeExceededError(StateTransitionMaxSizeExceededError), + + #[error(transparent)] + DataContractImmutablePropertiesUpdateError(DataContractImmutablePropertiesUpdateError), + + #[error(transparent)] + IncompatibleDataContractSchemaError(IncompatibleDataContractSchemaError), + + #[error(transparent)] + InvalidIdentityKeySignatureError(InvalidIdentityKeySignatureError), + + #[error(transparent)] + InvalidDataContractIdError(InvalidDataContractIdError), } impl From for BasicError { @@ -157,54 +119,24 @@ impl From for BasicError { #[derive(Error, Debug)] pub enum IndexError { - #[error("'{document_type}' document has more than '{index_limit}' unique indexes")] - UniqueIndicesLimitReachedError { - document_type: String, - index_limit: usize, - }, - - #[error("System property '{property_name}' is already indexed and can't be used in other indices for '{document_type}' document")] - SystemPropertyIndexAlreadyPresentError { - document_type: String, - index_definition: Index, - property_name: String, - }, - - #[error("'{property_name}' property is not defined in the '{document_type}' document")] - UndefinedIndexPropertyError { - document_type: String, - index_definition: Index, - property_name: String, - }, - - #[error("'{property_name}' property ofr '{document_type}' document has an invalid type '{property_type}' and cannot be use as an index")] - InvalidIndexPropertyTypeError { - document_type: String, - index_definition: Index, - property_name: String, - property_type: String, - }, - - #[error("Indexed property '{property_name}' for '{document_type}' document has an invalid constraint '{constraint_name}', reason: '{reason}'")] - InvalidIndexedPropertyConstraintError { - document_type: String, - index_definition: Index, - property_name: String, - constraint_name: String, - reason: String, - }, - - #[error( - "All or none of unique compound properties must be set for '{document_type}' document" - )] - InvalidCompoundIndexError { - document_type: String, - index_definition: Index, - }, - - #[error("Duplicate index definition for '{document_type} document")] - DuplicateIndexError { - document_type: String, - index_definition: Index, - }, + #[error(transparent)] + UniqueIndicesLimitReachedError(UniqueIndicesLimitReachedError), + + #[error(transparent)] + SystemPropertyIndexAlreadyPresentError(SystemPropertyIndexAlreadyPresentError), + + #[error(transparent)] + UndefinedIndexPropertyError(UndefinedIndexPropertyError), + + #[error(transparent)] + InvalidIndexPropertyTypeError(InvalidIndexPropertyTypeError), + + #[error(transparent)] + InvalidIndexedPropertyConstraintError(InvalidIndexedPropertyConstraintError), + + #[error(transparent)] + InvalidCompoundIndexError(InvalidCompoundIndexError), + + #[error(transparent)] + DuplicateIndexError(DuplicateIndexError), } diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_have_new_unique_index_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_have_new_unique_index_error.rs new file mode 100644 index 00000000000..47ab025815a --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_have_new_unique_index_error.rs @@ -0,0 +1,32 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Document with type {document_type} has a new unique index named '{index_name}'. Adding unique indices during Data Contract update is not allowed.")] +pub struct DataContractHaveNewUniqueIndexError { + document_type: String, + index_name: String, +} + +impl DataContractHaveNewUniqueIndexError { + pub fn new(document_type: String, index_name: String) -> Self { + Self { + document_type, + index_name, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + + pub fn index_name(&self) -> String { + self.index_name.clone() + } +} + +impl From for BasicError { + fn from(err: DataContractHaveNewUniqueIndexError) -> Self { + Self::DataContractHaveNewUniqueIndexError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_immutable_properties_update_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_immutable_properties_update_error.rs new file mode 100644 index 00000000000..6a8d6b1ba56 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_immutable_properties_update_error.rs @@ -0,0 +1,36 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Only $defs, version and documents fields are allowed to be updated. Forbidden operation '{operation}' on '{field_path}'")] +pub struct DataContractImmutablePropertiesUpdateError { + operation: String, + field_path: String, +} + +impl DataContractImmutablePropertiesUpdateError { + pub fn new(operation: String, field_path: String) -> Self { + Self { + operation, + field_path, + } + } + + pub fn operation(&self) -> String { + self.operation.clone() + } + + pub fn field_path(&self) -> String { + self.field_path.clone() + } +} + +impl From for ConsensusError { + fn from(err: DataContractImmutablePropertiesUpdateError) -> Self { + Self::BasicError(Box::new( + BasicError::DataContractImmutablePropertiesUpdateError(err), + )) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_invalid_index_definition_update_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_invalid_index_definition_update_error.rs new file mode 100644 index 00000000000..ba572bb89b4 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_invalid_index_definition_update_error.rs @@ -0,0 +1,36 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Document with type {document_type} has badly constructed index '{index_name}'. Existing properties in the indices should be defined in the beginning of it.")] +pub struct DataContractInvalidIndexDefinitionUpdateError { + document_type: String, + index_name: String, +} + +impl DataContractInvalidIndexDefinitionUpdateError { + pub fn new(document_type: String, index_name: String) -> Self { + Self { + document_type, + index_name, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + + pub fn index_name(&self) -> String { + self.index_name.clone() + } +} + +impl From for ConsensusError { + fn from(err: DataContractInvalidIndexDefinitionUpdateError) -> Self { + Self::BasicError(Box::new( + BasicError::DataContractInvalidIndexDefinitionUpdateError(err), + )) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_unique_indices_changed_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_unique_indices_changed_error.rs new file mode 100644 index 00000000000..ae4bea0a8bf --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/data_contract_unique_indices_changed_error.rs @@ -0,0 +1,36 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Document with type {document_type} has updated unique index named '{index_name}'. Change of unique indices is not allowed")] +pub struct DataContractUniqueIndicesChangedError { + document_type: String, + index_name: String, +} + +impl DataContractUniqueIndicesChangedError { + pub fn new(document_type: String, index_name: String) -> Self { + Self { + document_type, + index_name, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + + pub fn index_name(&self) -> String { + self.index_name.clone() + } +} + +impl From for ConsensusError { + fn from(err: DataContractUniqueIndicesChangedError) -> Self { + Self::BasicError(Box::new(BasicError::DataContractUniqueIndicesChangedError( + err, + ))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_index_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_index_error.rs new file mode 100644 index 00000000000..0ddca58f5e7 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_index_error.rs @@ -0,0 +1,37 @@ +use crate::consensus::basic::{BasicError, IndexError}; +use thiserror::Error; + +use crate::consensus::ConsensusError; +use crate::data_contract::document_type::Index; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Duplicate index definition for '{document_type} document")] +pub struct DuplicateIndexError { + document_type: String, + index_definition: Index, +} + +impl DuplicateIndexError { + pub fn new(document_type: String, index_definition: Index) -> Self { + Self { + document_type, + index_definition, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + + pub fn index_definition(&self) -> Index { + self.index_definition.clone() + } +} + +impl From for ConsensusError { + fn from(err: DuplicateIndexError) -> Self { + Self::BasicError(Box::new(BasicError::IndexError( + IndexError::DuplicateIndexError(err), + ))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_index_name_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_index_name_error.rs new file mode 100644 index 00000000000..851a5e3f340 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/duplicate_index_name_error.rs @@ -0,0 +1,34 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Duplicate index name '{duplicate_index_name}' defined in '{document_type}' document")] +pub struct DuplicateIndexNameError { + document_type: String, + duplicate_index_name: String, +} + +impl DuplicateIndexNameError { + pub fn new(document_type: String, duplicate_index_name: String) -> Self { + Self { + document_type, + duplicate_index_name, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + + pub fn duplicate_index_name(&self) -> String { + self.duplicate_index_name.clone() + } +} + +impl From for ConsensusError { + fn from(err: DuplicateIndexNameError) -> Self { + Self::BasicError(Box::new(BasicError::DuplicateIndexNameError(err))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/incompatible_data_contract_schema_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/incompatible_data_contract_schema_error.rs new file mode 100644 index 00000000000..41a12ba18ae --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/incompatible_data_contract_schema_error.rs @@ -0,0 +1,59 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::consensus::ConsensusError; +use crate::document::document_transition::document_base_transition::JsonValue; +use crate::identifier::Identifier; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Data Contract updated schema is not backward compatible with one defined in Data Contract wid id {data_contract_id}. Field: '{field_path}', Operation: '{operation}'" +)] +pub struct IncompatibleDataContractSchemaError { + data_contract_id: Identifier, + operation: String, + field_path: String, + old_schema: JsonValue, + new_schema: JsonValue, +} + +impl IncompatibleDataContractSchemaError { + pub fn new( + data_contract_id: Identifier, + operation: String, + field_path: String, + old_schema: JsonValue, + new_schema: JsonValue, + ) -> Self { + Self { + data_contract_id, + operation, + field_path, + old_schema, + new_schema, + } + } + + pub fn data_contract_id(&self) -> Identifier { + self.data_contract_id.clone() + } + pub fn operation(&self) -> String { + self.operation.clone() + } + pub fn field_path(&self) -> String { + self.field_path.clone() + } + pub fn old_schema(&self) -> JsonValue { + self.old_schema.clone() + } + pub fn new_schema(&self) -> JsonValue { + self.new_schema.clone() + } +} + +impl From for ConsensusError { + fn from(err: IncompatibleDataContractSchemaError) -> Self { + Self::BasicError(Box::new(BasicError::IncompatibleDataContractSchemaError( + err, + ))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/incompatible_re2_pattern_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/incompatible_re2_pattern_error.rs new file mode 100644 index 00000000000..de6a38e254c --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/incompatible_re2_pattern_error.rs @@ -0,0 +1,39 @@ +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Pattern '{pattern}' at '{path}' is not not compatible with Re2: {message}")] +pub struct IncompatibleRe2PatternError { + pattern: String, + path: String, + message: String, +} + +impl IncompatibleRe2PatternError { + pub fn new(pattern: String, path: String, message: String) -> Self { + Self { + pattern, + path, + message, + } + } + + pub fn pattern(&self) -> String { + self.pattern.clone() + } + + pub fn path(&self) -> String { + self.path.clone() + } + + pub fn message(&self) -> String { + self.message.clone() + } +} + +impl From for ConsensusError { + fn from(err: IncompatibleRe2PatternError) -> Self { + Self::IncompatibleRe2PatternError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_compound_index_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_compound_index_error.rs new file mode 100644 index 00000000000..0767c86661c --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_compound_index_error.rs @@ -0,0 +1,36 @@ +use crate::consensus::basic::{BasicError, IndexError}; +use thiserror::Error; + +use crate::consensus::ConsensusError; +use crate::data_contract::document_type::Index; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("All or none of unique compound properties must be set for '{document_type}' document")] +pub struct InvalidCompoundIndexError { + document_type: String, + index_definition: Index, +} + +impl InvalidCompoundIndexError { + pub fn new(document_type: String, index_definition: Index) -> Self { + Self { + document_type, + index_definition, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + pub fn index_definition(&self) -> Index { + self.index_definition.clone() + } +} + +impl From for ConsensusError { + fn from(err: InvalidCompoundIndexError) -> Self { + Self::BasicError(Box::new(BasicError::IndexError( + IndexError::InvalidCompoundIndexError(err), + ))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_data_contract_id_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_data_contract_id_error.rs new file mode 100644 index 00000000000..b13b25d0f70 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_data_contract_id_error.rs @@ -0,0 +1,31 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Data Contract Id must be {}, got {}", bs58::encode(expected_id).into_string(), bs58::encode(invalid_id).into_string())] +pub struct InvalidDataContractIdError { + expected_id: Vec, + invalid_id: Vec, +} + +impl InvalidDataContractIdError { + pub fn new(expected_id: Vec, invalid_id: Vec) -> Self { + Self { + expected_id, + invalid_id, + } + } + + pub fn expected_id(&self) -> Vec { + self.expected_id.clone() + } + pub fn invalid_id(&self) -> Vec { + self.invalid_id.clone() + } +} + +impl From for BasicError { + fn from(err: InvalidDataContractIdError) -> Self { + Self::InvalidDataContractIdError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_index_property_type_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_index_property_type_error.rs new file mode 100644 index 00000000000..c9d07f41c7f --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_index_property_type_error.rs @@ -0,0 +1,51 @@ +use crate::consensus::basic::{BasicError, IndexError}; +use thiserror::Error; + +use crate::consensus::ConsensusError; +use crate::data_contract::document_type::Index; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("'{property_name}' property of '{document_type}' document has an invalid type '{property_type}' and cannot be use as an index")] +pub struct InvalidIndexPropertyTypeError { + document_type: String, + index_definition: Index, + property_name: String, + property_type: String, +} + +impl InvalidIndexPropertyTypeError { + pub fn new( + document_type: String, + index_definition: Index, + property_name: String, + property_type: String, + ) -> Self { + Self { + document_type, + index_definition, + property_name, + property_type, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + pub fn index_definition(&self) -> Index { + self.index_definition.clone() + } + pub fn property_name(&self) -> String { + self.property_name.clone() + } + pub fn property_type(&self) -> String { + self.property_type.clone() + } +} + +impl From for ConsensusError { + fn from(err: InvalidIndexPropertyTypeError) -> Self { + Self::BasicError(Box::new(BasicError::IndexError( + IndexError::InvalidIndexPropertyTypeError(err), + ))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_indexed_property_constraint_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_indexed_property_constraint_error.rs new file mode 100644 index 00000000000..4ca69727d52 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_indexed_property_constraint_error.rs @@ -0,0 +1,57 @@ +use crate::consensus::basic::{BasicError, IndexError}; +use thiserror::Error; + +use crate::consensus::ConsensusError; +use crate::data_contract::document_type::Index; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Indexed property '{property_name}' for '{document_type}' document has an invalid constraint '{constraint_name}', reason: '{reason}'")] +pub struct InvalidIndexedPropertyConstraintError { + document_type: String, + index_definition: Index, + property_name: String, + constraint_name: String, + reason: String, +} + +impl InvalidIndexedPropertyConstraintError { + pub fn new( + document_type: String, + index_definition: Index, + property_name: String, + constraint_name: String, + reason: String, + ) -> Self { + Self { + document_type, + index_definition, + property_name, + constraint_name, + reason, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + pub fn index_definition(&self) -> Index { + self.index_definition.clone() + } + pub fn property_name(&self) -> String { + self.property_name.clone() + } + pub fn constraint_name(&self) -> String { + self.constraint_name.clone() + } + pub fn reason(&self) -> String { + self.reason.clone() + } +} + +impl From for ConsensusError { + fn from(err: InvalidIndexedPropertyConstraintError) -> Self { + Self::BasicError(Box::new(BasicError::IndexError( + IndexError::InvalidIndexedPropertyConstraintError(err), + ))) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_json_schema_ref_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_json_schema_ref_error.rs new file mode 100644 index 00000000000..8120f7a425c --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/invalid_json_schema_ref_error.rs @@ -0,0 +1,26 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid JSON Schema $ref: {ref_error}")] +pub struct InvalidJsonSchemaRefError { + ref_error: String, +} + +impl InvalidJsonSchemaRefError { + pub fn new(ref_error: String) -> Self { + Self { ref_error } + } + + pub fn ref_error(&self) -> String { + self.ref_error.clone() + } +} + +impl From for ConsensusError { + fn from(err: InvalidJsonSchemaRefError) -> Self { + Self::BasicError(Box::new(BasicError::InvalidJsonSchemaRefError(err))) + } +} 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 new file mode 100644 index 00000000000..b654b75be26 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs @@ -0,0 +1,34 @@ +mod data_contract_have_new_unique_index_error; +mod data_contract_immutable_properties_update_error; +mod data_contract_invalid_index_definition_update_error; +mod data_contract_unique_indices_changed_error; +mod duplicate_index_error; +mod duplicate_index_name_error; +mod incompatible_data_contract_schema_error; +mod incompatible_re2_pattern_error; +mod invalid_compound_index_error; +mod invalid_data_contract_id_error; +mod invalid_index_property_type_error; +mod invalid_indexed_property_constraint_error; +mod invalid_json_schema_ref_error; +mod system_property_index_already_present_error; +mod undefined_index_property_error; +mod unique_indices_limit_reached_error; + +pub use data_contract_have_new_unique_index_error::*; +pub use data_contract_immutable_properties_update_error::*; +pub use data_contract_invalid_index_definition_update_error::*; +pub use data_contract_unique_indices_changed_error::*; +pub use duplicate_index_error::*; +pub use duplicate_index_name_error::*; +pub use incompatible_data_contract_schema_error::*; +pub use incompatible_re2_pattern_error::*; +pub use invalid_compound_index_error::*; +pub use invalid_data_contract_id_error::*; +pub use invalid_index_property_type_error::*; +pub use invalid_indexed_property_constraint_error::*; +pub use invalid_json_schema_ref_error::*; +pub use invalid_json_schema_ref_error::*; +pub use system_property_index_already_present_error::*; +pub use undefined_index_property_error::*; +pub use unique_indices_limit_reached_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/system_property_index_already_present_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/system_property_index_already_present_error.rs new file mode 100644 index 00000000000..4c907abef41 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/system_property_index_already_present_error.rs @@ -0,0 +1,38 @@ +use crate::consensus::basic::IndexError; +use thiserror::Error; + +use crate::data_contract::document_type::Index; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("System property '{property_name}' is already indexed and can't be used in other indices for '{document_type}' document")] +pub struct SystemPropertyIndexAlreadyPresentError { + document_type: String, + index_definition: Index, + property_name: String, +} + +impl SystemPropertyIndexAlreadyPresentError { + pub fn new(document_type: String, index_definition: Index, property_name: String) -> Self { + Self { + document_type, + index_definition, + property_name, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + pub fn index_definition(&self) -> Index { + self.index_definition.clone() + } + pub fn property_name(&self) -> String { + self.property_name.clone() + } +} + +impl From for IndexError { + fn from(err: SystemPropertyIndexAlreadyPresentError) -> Self { + Self::SystemPropertyIndexAlreadyPresentError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/undefined_index_property_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/undefined_index_property_error.rs new file mode 100644 index 00000000000..6cf928abc05 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/undefined_index_property_error.rs @@ -0,0 +1,38 @@ +use crate::consensus::basic::IndexError; +use thiserror::Error; + +use crate::data_contract::document_type::Index; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("'{property_name}' property is not defined in the '{document_type}' document")] +pub struct UndefinedIndexPropertyError { + document_type: String, + index_definition: Index, + property_name: String, +} + +impl UndefinedIndexPropertyError { + pub fn new(document_type: String, index_definition: Index, property_name: String) -> Self { + Self { + document_type, + index_definition, + property_name, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + pub fn index_definition(&self) -> Index { + self.index_definition.clone() + } + pub fn property_name(&self) -> String { + self.property_name.clone() + } +} + +impl From for IndexError { + fn from(err: UndefinedIndexPropertyError) -> Self { + Self::UndefinedIndexPropertyError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/data_contract/unique_indices_limit_reached_error.rs b/packages/rs-dpp/src/errors/consensus/basic/data_contract/unique_indices_limit_reached_error.rs new file mode 100644 index 00000000000..99eb097031a --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/data_contract/unique_indices_limit_reached_error.rs @@ -0,0 +1,31 @@ +use crate::consensus::basic::IndexError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("'{document_type}' document has more than '{index_limit}' unique indexes")] +pub struct UniqueIndicesLimitReachedError { + document_type: String, + index_limit: usize, +} + +impl UniqueIndicesLimitReachedError { + pub fn new(document_type: String, index_limit: usize) -> Self { + Self { + document_type, + index_limit, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + pub fn index_limit(&self) -> usize { + self.index_limit + } +} + +impl From for IndexError { + fn from(err: UniqueIndicesLimitReachedError) -> Self { + Self::UniqueIndicesLimitReachedError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/decode/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/decode/mod.rs new file mode 100644 index 00000000000..2032dac6bbd --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/decode/mod.rs @@ -0,0 +1,2 @@ +mod protocol_version_parsing_error; +pub use protocol_version_parsing_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/basic/decode/protocol_version_parsing_error.rs b/packages/rs-dpp/src/errors/consensus/basic/decode/protocol_version_parsing_error.rs new file mode 100644 index 00000000000..0a5e22b9a67 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/decode/protocol_version_parsing_error.rs @@ -0,0 +1,21 @@ +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug)] +#[error("Can't read protocol version from serialized object: {parsing_error}")] +pub struct ProtocolVersionParsingError { + pub parsing_error: anyhow::Error, +} + +impl ProtocolVersionParsingError { + pub fn new(parsing_error: anyhow::Error) -> Self { + Self { parsing_error } + } +} + +impl From for ConsensusError { + fn from(err: ProtocolVersionParsingError) -> Self { + Self::ProtocolVersionParsingError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/duplicate_document_transitions_with_ids_error.rs b/packages/rs-dpp/src/errors/consensus/basic/document/duplicate_document_transitions_with_ids_error.rs new file mode 100644 index 00000000000..7b2b684362f --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/duplicate_document_transitions_with_ids_error.rs @@ -0,0 +1,24 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Document transitions with duplicate IDs {:?}", references)] +pub struct DuplicateDocumentTransitionsWithIdsError { + references: Vec<(String, Vec)>, +} + +impl DuplicateDocumentTransitionsWithIdsError { + pub fn new(references: Vec<(String, Vec)>) -> Self { + Self { references } + } + + pub fn references(&self) -> Vec<(String, Vec)> { + self.references.clone() + } +} + +impl From for BasicError { + fn from(err: DuplicateDocumentTransitionsWithIdsError) -> Self { + Self::DuplicateDocumentTransitionsWithIdsError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/duplicate_document_transitions_with_indices_error.rs b/packages/rs-dpp/src/errors/consensus/basic/document/duplicate_document_transitions_with_indices_error.rs new file mode 100644 index 00000000000..43996e1b714 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/duplicate_document_transitions_with_indices_error.rs @@ -0,0 +1,27 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error( + "Document transitions with duplicate unique properties: {:?}", + references +)] +pub struct DuplicateDocumentTransitionsWithIndicesError { + references: Vec<(String, Vec)>, +} + +impl DuplicateDocumentTransitionsWithIndicesError { + pub fn new(references: Vec<(String, Vec)>) -> Self { + Self { references } + } + + pub fn references(&self) -> Vec<(String, Vec)> { + self.references.clone() + } +} + +impl From for BasicError { + fn from(err: DuplicateDocumentTransitionsWithIndicesError) -> Self { + Self::DuplicateDocumentTransitionsWithIndicesError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/inconsistent_compound_index_data_error.rs b/packages/rs-dpp/src/errors/consensus/basic/document/inconsistent_compound_index_data_error.rs new file mode 100644 index 00000000000..c2550884183 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/inconsistent_compound_index_data_error.rs @@ -0,0 +1,34 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error( + "Unique compound index properties {:?} are partially set for {document_type}", + index_properties +)] +pub struct InconsistentCompoundIndexDataError { + index_properties: Vec, + document_type: String, +} + +impl InconsistentCompoundIndexDataError { + pub fn new(index_properties: Vec, document_type: String) -> Self { + Self { + index_properties, + document_type, + } + } + + pub fn index_properties(&self) -> Vec { + self.index_properties.clone() + } + pub fn document_type(&self) -> String { + self.document_type.clone() + } +} + +impl From for BasicError { + fn from(err: InconsistentCompoundIndexDataError) -> Self { + Self::InconsistentCompoundIndexDataError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_transition_action_error.rs b/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_transition_action_error.rs new file mode 100644 index 00000000000..5a47ade3059 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_transition_action_error.rs @@ -0,0 +1,24 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Document transition action {} is not supported", action)] +pub struct InvalidDocumentTransitionActionError { + action: String, +} + +impl InvalidDocumentTransitionActionError { + pub fn new(action: String) -> Self { + Self { action } + } + + pub fn action(&self) -> String { + self.action.clone() + } +} + +impl From for BasicError { + fn from(err: InvalidDocumentTransitionActionError) -> Self { + Self::InvalidDocumentTransitionActionError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_transition_id_error.rs b/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_transition_id_error.rs new file mode 100644 index 00000000000..e4a49c8236d --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_transition_id_error.rs @@ -0,0 +1,37 @@ +use crate::consensus::basic::BasicError; +use crate::identifier::Identifier; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error( + "Invalid document transition id {}, expected {}", + invalid_id, + expected_id +)] +pub struct InvalidDocumentTransitionIdError { + expected_id: Identifier, + invalid_id: Identifier, +} + +impl InvalidDocumentTransitionIdError { + pub fn new(expected_id: Identifier, invalid_id: Identifier) -> Self { + Self { + expected_id, + invalid_id, + } + } + + pub fn expected_id(&self) -> Identifier { + self.expected_id.clone() + } + + pub fn invalid_id(&self) -> Identifier { + self.invalid_id.clone() + } +} + +impl From for BasicError { + fn from(err: InvalidDocumentTransitionIdError) -> Self { + Self::InvalidDocumentTransitionIdError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_type_error.rs b/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_type_error.rs new file mode 100644 index 00000000000..585d3e5a318 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/invalid_document_type_error.rs @@ -0,0 +1,34 @@ +use thiserror::Error; + +use crate::data_contract::errors::DataContractError; +use crate::identifier::Identifier; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Data Contract {data_contract_id} doesn't define document with the type {document_type}")] +pub struct InvalidDocumentTypeError { + document_type: String, + data_contract_id: Identifier, +} + +impl InvalidDocumentTypeError { + pub fn new(document_type: String, data_contract_id: Identifier) -> Self { + Self { + document_type, + data_contract_id, + } + } + + pub fn document_type(&self) -> String { + self.document_type.clone() + } + + pub fn data_contract_id(&self) -> Identifier { + self.data_contract_id.clone() + } +} + +impl From for DataContractError { + fn from(err: InvalidDocumentTypeError) -> Self { + Self::InvalidDocumentTypeError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/document/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/document/mod.rs new file mode 100644 index 00000000000..15f2d90bd90 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/document/mod.rs @@ -0,0 +1,13 @@ +mod duplicate_document_transitions_with_ids_error; +mod duplicate_document_transitions_with_indices_error; +mod inconsistent_compound_index_data_error; +mod invalid_document_transition_action_error; +mod invalid_document_transition_id_error; +mod invalid_document_type_error; + +pub use duplicate_document_transitions_with_ids_error::*; +pub use duplicate_document_transitions_with_indices_error::*; +pub use inconsistent_compound_index_data_error::*; +pub use invalid_document_transition_action_error::*; +pub use invalid_document_transition_id_error::*; +pub use invalid_document_type_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_key_signature_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_key_signature_error.rs new file mode 100644 index 00000000000..a38e93bd09a --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_key_signature_error.rs @@ -0,0 +1,26 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +use crate::identity::KeyID; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Identity key {public_key_id} has invalid signature")] +pub struct InvalidIdentityKeySignatureError { + public_key_id: KeyID, +} + +impl InvalidIdentityKeySignatureError { + pub fn new(public_key_id: KeyID) -> Self { + Self { public_key_id } + } + + pub fn public_key_id(&self) -> KeyID { + self.public_key_id.clone() + } +} + +impl From for BasicError { + fn from(err: InvalidIdentityKeySignatureError) -> Self { + Self::InvalidIdentityKeySignatureError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs index 2275fb0a624..dbaebaacba5 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs @@ -13,6 +13,7 @@ pub use invalid_credit_withdrawal_transition_output_script_error::*; pub use invalid_credit_withdrawal_transition_pooling_error::*; pub use invalid_identity_asset_lock_transaction_error::*; pub use invalid_identity_asset_lock_transaction_output_error::*; +pub use invalid_identity_key_signature_error::*; pub use invalid_identity_public_key_data_error::*; pub use invalid_identity_public_key_security_level_error::*; pub use invalid_instant_asset_lock_proof_error::*; @@ -34,6 +35,7 @@ mod invalid_credit_withdrawal_transition_output_script_error; mod invalid_credit_withdrawal_transition_pooling_error; mod invalid_identity_asset_lock_transaction_error; mod invalid_identity_asset_lock_transaction_output_error; +mod invalid_identity_key_signature_error; mod invalid_identity_public_key_data_error; mod invalid_identity_public_key_security_level_error; mod invalid_instant_asset_lock_proof_error; diff --git a/packages/rs-dpp/src/errors/consensus/basic/invalid_data_contract_version_error.rs b/packages/rs-dpp/src/errors/consensus/basic/invalid_data_contract_version_error.rs new file mode 100644 index 00000000000..427a480eeec --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/invalid_data_contract_version_error.rs @@ -0,0 +1,32 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Data Contract version must be {expected_version}, go {version}")] +pub struct InvalidDataContractVersionError { + expected_version: u32, + version: u32, +} + +impl InvalidDataContractVersionError { + pub fn new(expected_version: u32, version: u32) -> Self { + Self { + expected_version, + version, + } + } + + pub fn expected_version(&self) -> u32 { + self.expected_version + } + + pub fn version(&self) -> u32 { + self.version + } +} + +impl From for BasicError { + fn from(err: InvalidDataContractVersionError) -> Self { + Self::InvalidDataContractVersionError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/invalid_identifier_error.rs b/packages/rs-dpp/src/errors/consensus/basic/invalid_identifier_error.rs new file mode 100644 index 00000000000..cb1dba57de3 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/invalid_identifier_error.rs @@ -0,0 +1,32 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid {}: {}", identifier_name, error)] +pub struct InvalidIdentifierError { + identifier_name: String, + error: String, +} + +impl InvalidIdentifierError { + pub fn new(identifier_name: String, error: String) -> Self { + Self { + identifier_name, + error, + } + } + + pub fn identifier_name(&self) -> String { + self.identifier_name.clone() + } + + pub fn error(&self) -> String { + self.error.clone() + } +} + +impl From for BasicError { + fn from(err: InvalidIdentifierError) -> Self { + Self::InvalidIdentifierError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/mod.rs index 252f6d0943e..f9d16f0a3a6 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/mod.rs @@ -5,11 +5,17 @@ pub use json_schema_error::*; pub use test_consensus_error::*; pub use unsupported_protocol_version_error::*; +pub mod data_contract; +pub mod decode; +pub mod document; pub mod identity; -mod incompatible_protocol_version_error; -mod json_schema_error; +pub mod incompatible_protocol_version_error; +pub mod json_schema_error; #[cfg(test)] -mod test_consensus_error; -mod unsupported_protocol_version_error; +pub mod test_consensus_error; +pub mod unsupported_protocol_version_error; -mod abstract_basic_error; +pub mod abstract_basic_error; +pub mod invalid_data_contract_version_error; +pub mod invalid_identifier_error; +pub mod state_transition; diff --git a/packages/rs-dpp/src/errors/consensus/basic/state_transition/invalid_state_transition_type_error.rs b/packages/rs-dpp/src/errors/consensus/basic/state_transition/invalid_state_transition_type_error.rs new file mode 100644 index 00000000000..dd0784d4bfd --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/state_transition/invalid_state_transition_type_error.rs @@ -0,0 +1,25 @@ +use thiserror::Error; + +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid State Transition type {transition_type}")] +pub struct InvalidStateTransitionTypeError { + transition_type: u8, +} + +impl InvalidStateTransitionTypeError { + pub fn new(transition_type: u8) -> Self { + Self { transition_type } + } + + pub fn transition_type(&self) -> u8 { + self.transition_type + } +} + +impl From for ProtocolError { + fn from(err: InvalidStateTransitionTypeError) -> Self { + Self::InvalidStateTransitionTypeError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/state_transition/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/state_transition/mod.rs new file mode 100644 index 00000000000..eccba51d965 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/state_transition/mod.rs @@ -0,0 +1,5 @@ +mod invalid_state_transition_type_error; +mod state_transition_max_size_exceeded_error; + +pub use invalid_state_transition_type_error::*; +pub use state_transition_max_size_exceeded_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/basic/state_transition/state_transition_max_size_exceeded_error.rs b/packages/rs-dpp/src/errors/consensus/basic/state_transition/state_transition_max_size_exceeded_error.rs new file mode 100644 index 00000000000..40aac4b25ff --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/state_transition/state_transition_max_size_exceeded_error.rs @@ -0,0 +1,31 @@ +use crate::consensus::basic::BasicError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("State transition size {actual_size_kbytes} KB is more than maximum {max_size_kbytes} KB")] +pub struct StateTransitionMaxSizeExceededError { + actual_size_kbytes: usize, + max_size_kbytes: usize, +} + +impl StateTransitionMaxSizeExceededError { + pub fn new(actual_size_kbytes: usize, max_size_kbytes: usize) -> Self { + Self { + actual_size_kbytes, + max_size_kbytes, + } + } + + pub fn actual_size_kbytes(&self) -> usize { + self.actual_size_kbytes + } + pub fn max_size_kbytes(&self) -> usize { + self.max_size_kbytes + } +} + +impl From for BasicError { + fn from(err: StateTransitionMaxSizeExceededError) -> Self { + Self::StateTransitionMaxSizeExceededError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/identity_not_found_error.rs b/packages/rs-dpp/src/errors/consensus/signature/identity_not_found_error.rs new file mode 100644 index 00000000000..18613962366 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/identity_not_found_error.rs @@ -0,0 +1,27 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identifier::Identifier; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Identity {identity_id} not found")] +pub struct IdentityNotFoundError { + identity_id: Identifier, +} + +impl IdentityNotFoundError { + pub fn new(identity_id: Identifier) -> Self { + Self { identity_id } + } + + pub fn identity_id(&self) -> Identifier { + self.identity_id.clone() + } +} + +impl From for ConsensusError { + fn from(err: IdentityNotFoundError) -> Self { + Self::SignatureError(SignatureError::IdentityNotFoundError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/invalid_identity_public_key_type_error.rs b/packages/rs-dpp/src/errors/consensus/signature/invalid_identity_public_key_type_error.rs new file mode 100644 index 00000000000..cbd77b97495 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/invalid_identity_public_key_type_error.rs @@ -0,0 +1,27 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identity::KeyType; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Unsupported signature type {public_key_type}. Please use ECDSA (0), BLS (1) or ECDSA_HASH160 (2) keys to sign the state transition")] +pub struct InvalidIdentityPublicKeyTypeError { + public_key_type: KeyType, +} + +impl InvalidIdentityPublicKeyTypeError { + pub fn new(public_key_type: KeyType) -> Self { + Self { public_key_type } + } + + pub fn public_key_type(&self) -> KeyType { + self.public_key_type.clone() + } +} + +impl From for ConsensusError { + fn from(err: InvalidIdentityPublicKeyTypeError) -> Self { + Self::SignatureError(SignatureError::InvalidIdentityPublicKeyTypeError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_security_level_error.rs b/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_security_level_error.rs new file mode 100644 index 00000000000..cf155a36d76 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_security_level_error.rs @@ -0,0 +1,39 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identity::SecurityLevel; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid public key security level {public_key_security_level}. The state transition requires {required_key_security_level}")] +pub struct InvalidSignaturePublicKeySecurityLevelError { + public_key_security_level: SecurityLevel, + required_key_security_level: SecurityLevel, +} + +impl InvalidSignaturePublicKeySecurityLevelError { + pub fn new( + public_key_security_level: SecurityLevel, + required_key_security_level: SecurityLevel, + ) -> Self { + Self { + public_key_security_level, + required_key_security_level, + } + } + + pub fn public_key_security_level(&self) -> SecurityLevel { + self.public_key_security_level.clone() + } + pub fn required_key_security_level(&self) -> SecurityLevel { + self.required_key_security_level.clone() + } +} + +impl From for ConsensusError { + fn from(err: InvalidSignaturePublicKeySecurityLevelError) -> Self { + Self::SignatureError(SignatureError::InvalidSignaturePublicKeySecurityLevelError( + err, + )) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/missing_public_key_error.rs b/packages/rs-dpp/src/errors/consensus/signature/missing_public_key_error.rs new file mode 100644 index 00000000000..abe13ad9a46 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/missing_public_key_error.rs @@ -0,0 +1,27 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identity::KeyID; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Public key {public_key_id} doesn't exist")] +pub struct MissingPublicKeyError { + public_key_id: KeyID, +} + +impl MissingPublicKeyError { + pub fn new(public_key_id: KeyID) -> Self { + Self { public_key_id } + } + + pub fn public_key_id(&self) -> KeyID { + self.public_key_id + } +} + +impl From for ConsensusError { + fn from(err: MissingPublicKeyError) -> Self { + Self::SignatureError(SignatureError::MissingPublicKeyError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/mod.rs b/packages/rs-dpp/src/errors/consensus/signature/mod.rs index 9b411a98eff..db3f3895781 100644 --- a/packages/rs-dpp/src/errors/consensus/signature/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/signature/mod.rs @@ -1,42 +1,44 @@ +mod identity_not_found_error; +mod invalid_identity_public_key_type_error; +mod invalid_signature_public_key_security_level_error; +mod missing_public_key_error; +mod public_key_is_disabled_error; +mod public_key_security_level_not_met_error; +mod wrong_public_key_purpose_error; + use thiserror::Error; -use crate::{ - identity::{KeyID, KeyType, Purpose, SecurityLevel}, - prelude::Identifier, -}; +pub use crate::consensus::signature::identity_not_found_error::IdentityNotFoundError; +pub use crate::consensus::signature::invalid_identity_public_key_type_error::InvalidIdentityPublicKeyTypeError; +pub use crate::consensus::signature::invalid_signature_public_key_security_level_error::InvalidSignaturePublicKeySecurityLevelError; +pub use crate::consensus::signature::missing_public_key_error::MissingPublicKeyError; +pub use crate::consensus::signature::public_key_is_disabled_error::PublicKeyIsDisabledError; +pub use crate::consensus::signature::public_key_security_level_not_met_error::PublicKeySecurityLevelNotMetError; +pub use crate::consensus::signature::wrong_public_key_purpose_error::WrongPublicKeyPurposeError; #[derive(Error, Debug)] pub enum SignatureError { - #[error("Public key {public_key_id} doesn't exist")] - MissingPublicKeyError { public_key_id: KeyID }, + #[error(transparent)] + MissingPublicKeyError(MissingPublicKeyError), - #[error("Unsupported signature type {public_key_type}. Please use ECDSA (0), BLS (1) or ECDSA_HASH160 (2) keys to sign the state transition")] - InvalidIdentityPublicKeyTypeError { public_key_type: KeyType }, + #[error(transparent)] + InvalidIdentityPublicKeyTypeError(InvalidIdentityPublicKeyTypeError), #[error("Invalid State Transition signature")] InvalidStateTransitionSignatureError, - #[error("Identity {identity_id} not found")] - IdentityNotFoundError { identity_id: Identifier }, - - #[error("Invalid public key security level {public_key_security_level}. The state transition requires {required_key_security_level}")] - InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level: SecurityLevel, - required_key_security_level: SecurityLevel, - }, - - #[error("Identity key {public_key_id} is disabled")] - PublicKeyIsDisabledError { public_key_id: KeyID }, - - #[error("Invalid security level {public_key_security_level}. This state transition requires at least {required_security_level}")] - PublicKeySecurityLevelNotMetError { - public_key_security_level: SecurityLevel, - required_security_level: SecurityLevel, - }, - - #[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {key_purpose_requirement}")] - WrongPublicKeyPurposeError { - public_key_purpose: Purpose, - key_purpose_requirement: Purpose, - }, + #[error(transparent)] + IdentityNotFoundError(IdentityNotFoundError), + + #[error(transparent)] + InvalidSignaturePublicKeySecurityLevelError(InvalidSignaturePublicKeySecurityLevelError), + + #[error(transparent)] + PublicKeyIsDisabledError(PublicKeyIsDisabledError), + + #[error(transparent)] + PublicKeySecurityLevelNotMetError(PublicKeySecurityLevelNotMetError), + + #[error(transparent)] + WrongPublicKeyPurposeError(WrongPublicKeyPurposeError), } diff --git a/packages/rs-dpp/src/errors/consensus/signature/public_key_is_disabled_error.rs b/packages/rs-dpp/src/errors/consensus/signature/public_key_is_disabled_error.rs new file mode 100644 index 00000000000..067d3975492 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/public_key_is_disabled_error.rs @@ -0,0 +1,27 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identity::KeyID; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Identity key {public_key_id} is disabled")] +pub struct PublicKeyIsDisabledError { + public_key_id: KeyID, +} + +impl PublicKeyIsDisabledError { + pub fn new(public_key_id: KeyID) -> Self { + Self { public_key_id } + } + + pub fn public_key_id(&self) -> KeyID { + self.public_key_id.clone() + } +} + +impl From for ConsensusError { + fn from(err: PublicKeyIsDisabledError) -> Self { + Self::SignatureError(SignatureError::PublicKeyIsDisabledError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/public_key_security_level_not_met_error.rs b/packages/rs-dpp/src/errors/consensus/signature/public_key_security_level_not_met_error.rs new file mode 100644 index 00000000000..d959065038f --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/public_key_security_level_not_met_error.rs @@ -0,0 +1,37 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identity::SecurityLevel; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid security level {public_key_security_level}. This state transition requires at least {required_security_level}")] +pub struct PublicKeySecurityLevelNotMetError { + public_key_security_level: SecurityLevel, + required_security_level: SecurityLevel, +} + +impl PublicKeySecurityLevelNotMetError { + pub fn new( + public_key_security_level: SecurityLevel, + required_security_level: SecurityLevel, + ) -> Self { + Self { + public_key_security_level, + required_security_level, + } + } + + pub fn public_key_security_level(&self) -> SecurityLevel { + self.public_key_security_level.clone() + } + pub fn required_security_level(&self) -> SecurityLevel { + self.required_security_level.clone() + } +} + +impl From for ConsensusError { + fn from(err: PublicKeySecurityLevelNotMetError) -> Self { + Self::SignatureError(SignatureError::PublicKeySecurityLevelNotMetError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs b/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs new file mode 100644 index 00000000000..c825fcb31ca --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs @@ -0,0 +1,34 @@ +use thiserror::Error; + +use crate::consensus::signature::SignatureError; +use crate::consensus::ConsensusError; +use crate::identity::Purpose; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {key_purpose_requirement}")] +pub struct WrongPublicKeyPurposeError { + public_key_purpose: Purpose, + key_purpose_requirement: Purpose, +} + +impl WrongPublicKeyPurposeError { + pub fn new(public_key_purpose: Purpose, key_purpose_requirement: Purpose) -> Self { + Self { + public_key_purpose, + key_purpose_requirement, + } + } + + pub fn public_key_purpose(&self) -> Purpose { + self.public_key_purpose.clone() + } + pub fn key_purpose_requirement(&self) -> Purpose { + self.key_purpose_requirement.clone() + } +} + +impl From for ConsensusError { + fn from(err: WrongPublicKeyPurposeError) -> Self { + Self::SignatureError(SignatureError::WrongPublicKeyPurposeError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/dpp_init_error.rs b/packages/rs-dpp/src/errors/dpp_init_error.rs index a7bce37cb8a..68e1e7cbd11 100644 --- a/packages/rs-dpp/src/errors/dpp_init_error.rs +++ b/packages/rs-dpp/src/errors/dpp_init_error.rs @@ -5,9 +5,9 @@ use thiserror::Error; #[derive(Error, Debug)] pub enum DashPlatformProtocolInitError { - #[error("{0}")] + #[error(transparent)] SchemaDeserializationError(serde_json::Error), - #[error("{0}")] + #[error(transparent)] ValidationError(ValidationError<'static>), #[error("Loaded Schema is invalid: {0}")] InvalidSchemaError(&'static str), diff --git a/packages/rs-dpp/src/errors/errors.rs b/packages/rs-dpp/src/errors/errors.rs index 4eb99258740..f7316a58b18 100644 --- a/packages/rs-dpp/src/errors/errors.rs +++ b/packages/rs-dpp/src/errors/errors.rs @@ -1,12 +1,17 @@ use serde_json::Value as JsonValue; use thiserror::Error; +use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; +use crate::consensus::signature::InvalidSignaturePublicKeySecurityLevelError; use crate::consensus::ConsensusError; use crate::data_contract::errors::*; +use crate::data_contract::state_transition::errors::MissingDataContractIdError; +use crate::data_contract::state_transition::errors::PublicKeyIsDisabledError; use crate::document::errors::*; -use crate::identity::{IdentityPublicKey, KeyType, Purpose, SecurityLevel}; -use crate::prelude::Identifier; -use crate::state_transition::StateTransition; +use crate::state_transition::errors::{ + InvalidIdentityPublicKeyTypeError, InvalidSignaturePublicKeyError, PublicKeyMismatchError, + PublicKeySecurityLevelNotMetError, StateTransitionIsNotSignedError, WrongPublicKeyPurposeError, +}; use crate::{CompatibleProtocolVersionIsNotDefinedError, NonConsensusError, SerdeParsingError}; use platform_value::Error as ValueError; @@ -56,30 +61,18 @@ pub enum ProtocolError { Generic(String), // State Transition Errors - #[error("Invalid signature type")] - InvalidIdentityPublicKeyTypeError { public_key_type: KeyType }, - #[error("State Transition is not signed")] - StateTransitionIsNotIsSignedError { state_transition: StateTransition }, - #[error( - "Invalid key security level: {public_key_security_level}. The state transition requires at least: {required_security_level}" - )] - PublicKeySecurityLevelNotMetError { - public_key_security_level: SecurityLevel, - required_security_level: SecurityLevel, - }, - #[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {key_purpose_requirement}")] - WrongPublicKeyPurposeError { - public_key_purpose: Purpose, - key_purpose_requirement: Purpose, - }, - #[error("Public key generation error {0}")] - PublicKeyGenerationError(String), - - #[error("Public key mismatched")] - PublicKeyMismatchError { public_key: IdentityPublicKey }, - - #[error("Invalid signature public key")] - InvalidSignaturePublicKeyError { public_key: Vec }, + #[error(transparent)] + InvalidIdentityPublicKeyTypeError(InvalidIdentityPublicKeyTypeError), + #[error(transparent)] + StateTransitionIsNotSignedError(StateTransitionIsNotSignedError), + #[error(transparent)] + PublicKeySecurityLevelNotMetError(PublicKeySecurityLevelNotMetError), + #[error(transparent)] + WrongPublicKeyPurposeError(WrongPublicKeyPurposeError), + #[error(transparent)] + PublicKeyMismatchError(PublicKeyMismatchError), + #[error(transparent)] + InvalidSignaturePublicKeyError(InvalidSignaturePublicKeyError), // TODO decide if it should be a string #[error("Non-Consensus error: {0}")] @@ -92,32 +85,29 @@ pub enum ProtocolError { #[error("Data Contract already exists")] DataContractAlreadyExistsError, - #[error("Invalid Data Contract: {errors:?}")] - InvalidDataContractError { - errors: Vec, - raw_data_contract: JsonValue, - }, + #[error(transparent)] + InvalidDataContractError(InvalidDataContractError), - #[error("Data Contract is not present")] - DataContractNotPresentError { data_contract_id: Identifier }, + #[error(transparent)] + InvalidDocumentTypeError(InvalidDocumentTypeError), - #[error("Invalid public key security level {public_key_security_level}. This state transition requires {required_security_level}")] - InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level: SecurityLevel, - required_security_level: SecurityLevel, - }, + #[error(transparent)] + DataContractNotPresentError(DataContractNotPresentError), - #[error("State Transition type is not present")] - InvalidStateTransitionTypeError, + #[error(transparent)] + InvalidSignaturePublicKeySecurityLevelError(InvalidSignaturePublicKeySecurityLevelError), - #[error("$dataContractId is not present")] - MissingDataContractIdError { raw_document_transition: JsonValue }, + #[error(transparent)] + InvalidStateTransitionTypeError(InvalidStateTransitionTypeError), - #[error("Public key is disabled")] - PublicKeyIsDisabledError { public_key: IdentityPublicKey }, + #[error(transparent)] + MissingDataContractIdError(MissingDataContractIdError), - #[error("Identity is not present")] - IdentityNotPresentError { id: Identifier }, + #[error(transparent)] + PublicKeyIsDisabledError(PublicKeyIsDisabledError), + + #[error(transparent)] + IdentityNotPresentError(IdentityNotPresentError), /// Error #[error("overflow error: {0}")] @@ -136,6 +126,9 @@ pub enum ProtocolError { errors: Vec, raw_identity: JsonValue, }, + + #[error("Public key generation error {0}")] + PublicKeyGenerationError(String), } impl From for ProtocolError { diff --git a/packages/rs-dpp/src/errors/non_consensus_error.rs b/packages/rs-dpp/src/errors/non_consensus_error.rs index 44ad0a627d1..c39b280ea67 100644 --- a/packages/rs-dpp/src/errors/non_consensus_error.rs +++ b/packages/rs-dpp/src/errors/non_consensus_error.rs @@ -8,17 +8,17 @@ use crate::{ pub enum NonConsensusError { #[error("Unexpected serde parsing error: {0:#}")] SerdeParsingError(SerdeParsingError), - #[error("{0}")] + #[error(transparent)] CompatibleProtocolVersionIsNotDefinedError(CompatibleProtocolVersionIsNotDefinedError), - #[error("{0}")] + #[error("SerdeJsonError: {0}")] SerdeJsonError(String), - #[error("{0}")] + #[error(transparent)] InvalidVectorSizeError(InvalidVectorSizeError), - #[error("{0}")] + #[error("StateRepositoryFetchError: {0}")] StateRepositoryFetchError(String), - #[error("{0}")] + #[error("IdentifierCreateError: {0}")] IdentifierCreateError(String), - #[error("{0}")] + #[error("IdentityPublicKeyCreateError: {0}")] IdentityPublicKeyCreateError(String), /// When dynamic `Value` is validated it requires some specific properties to properly work diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs index 5d0132b7c11..0dfa0ca7f41 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs @@ -3,13 +3,12 @@ use std::sync::Arc; use anyhow::Result; +use crate::consensus::signature::IdentityNotFoundError; use crate::{ - consensus::basic::{identity::IdentityInsufficientBalanceError, BasicError}, + consensus::basic::identity::IdentityInsufficientBalanceError, identity::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition, - state_repository::StateRepositoryLike, - state_transition::StateTransitionLike, - validation::ValidationResult, - NonConsensusError, StateError, + state_repository::StateRepositoryLike, state_transition::StateTransitionLike, + validation::ValidationResult, NonConsensusError, StateError, }; pub struct IdentityCreditWithdrawalTransitionValidator @@ -47,9 +46,7 @@ where .map_err(|e| NonConsensusError::StateRepositoryFetchError(e.to_string()))?; let Some(existing_identity) = maybe_existing_identity else { - let err = BasicError::IdentityNotFoundError { - identity_id: state_transition.identity_id, - }; + let err = IdentityNotFoundError::new(state_transition.identity_id); result.add_error(err); diff --git a/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs b/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs index 0e56981309b..c078da110b0 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs @@ -3,9 +3,9 @@ use serde_json::Value; use std::convert::TryInto; use std::sync::Arc; +use crate::consensus::signature::{IdentityNotFoundError, SignatureError}; use crate::{ block_time_window::validate_time_in_block_time_window::validate_time_in_block_time_window, - consensus::basic::BasicError, identity::validation::{RequiredPurposeAndSecurityLevelValidator, TPublicKeysValidator}, state_repository::StateRepositoryLike, state_transition::StateTransitionLike, @@ -56,9 +56,9 @@ where let stored_identity = match maybe_stored_identity { None => { - validation_result.add_error(BasicError::IdentityNotFoundError { - identity_id: state_transition.get_identity_id().to_owned(), - }); + validation_result.add_error(SignatureError::IdentityNotFoundError( + IdentityNotFoundError::new(state_transition.get_identity_id().to_owned()), + )); return Ok(validation_result); } Some(identity) => identity, diff --git a/packages/rs-dpp/src/identity/state_transition/validate_public_key_signatures.rs b/packages/rs-dpp/src/identity/state_transition/validate_public_key_signatures.rs index b79b873543e..07ada1f637f 100644 --- a/packages/rs-dpp/src/identity/state_transition/validate_public_key_signatures.rs +++ b/packages/rs-dpp/src/identity/state_transition/validate_public_key_signatures.rs @@ -1,5 +1,7 @@ use serde_json::Value; +use crate::consensus::basic::identity::InvalidIdentityKeySignatureError; +use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; use crate::identity::state_transition::identity_public_key_transitions::IdentityPublicKeyCreateTransition; use crate::{ consensus::{basic::BasicError, ConsensusError}, @@ -94,9 +96,9 @@ pub fn validate_public_key_signatures<'a, T: BlsModule>( let maybe_invalid_public_key_transition = find_invalid_public_key(&mut state_transition, add_public_key_transitions, bls); if let Some(invalid_key_transition) = maybe_invalid_public_key_transition { - validation_result.add_error(BasicError::InvalidIdentityKeySignatureError { - public_key_id: invalid_key_transition.id, - }) + validation_result.add_error(BasicError::InvalidIdentityKeySignatureError( + InvalidIdentityKeySignatureError::new(invalid_key_transition.id), + )) } Ok(validation_result) @@ -104,7 +106,9 @@ pub fn validate_public_key_signatures<'a, T: BlsModule>( fn invalid_state_transition_type_error(transition_type: u8) -> ProtocolError { ProtocolError::AbstractConsensusError(Box::new(ConsensusError::BasicError(Box::new( - BasicError::InvalidStateTransitionTypeError { transition_type }, + BasicError::InvalidStateTransitionTypeError(InvalidStateTransitionTypeError::new( + transition_type, + )), )))) } diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs index fe87d540745..9fdc182c0db 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs @@ -4,6 +4,9 @@ use dashcore::signer; use serde::Serialize; use serde_json::Value as JsonValue; +use crate::state_transition::errors::{ + InvalidIdentityPublicKeyTypeError, StateTransitionIsNotSignedError, +}; use crate::{ identity::KeyType, prelude::ProtocolError, @@ -77,9 +80,9 @@ pub trait StateTransitionLike: // https://github.com/dashevo/platform/blob/6b02b26e5cd3a7c877c5fdfe40c4a4385a8dda15/packages/js-dpp/lib/stateTransition/AbstractStateTransition.js#L187 // is to return the error for the BIP13_SCRIPT_HASH KeyType::BIP13_SCRIPT_HASH => { - return Err(ProtocolError::InvalidIdentityPublicKeyTypeError { - public_key_type: key_type, - }) + return Err(ProtocolError::InvalidIdentityPublicKeyTypeError( + InvalidIdentityPublicKeyTypeError::new(key_type), + )) } }; Ok(()) @@ -97,9 +100,9 @@ pub trait StateTransitionLike: self.verify_ecdsa_hash_160_signature_by_public_key_hash(public_key) } KeyType::BLS12_381 => self.verify_bls_signature_by_public_key(public_key, bls), - KeyType::BIP13_SCRIPT_HASH => { - Err(ProtocolError::InvalidIdentityPublicKeyTypeError { public_key_type }) - } + KeyType::BIP13_SCRIPT_HASH => Err(ProtocolError::InvalidIdentityPublicKeyTypeError( + InvalidIdentityPublicKeyTypeError::new(public_key_type), + )), } } @@ -108,9 +111,9 @@ pub trait StateTransitionLike: public_key_hash: &[u8], ) -> Result<(), ProtocolError> { if self.get_signature().is_empty() { - return Err(ProtocolError::StateTransitionIsNotIsSignedError { - state_transition: self.clone().into(), - }); + return Err(ProtocolError::StateTransitionIsNotSignedError( + StateTransitionIsNotSignedError::new(self.clone().into()), + )); } let data_hash = self.hash(true)?; Ok(signer::verify_hash_signature( @@ -123,9 +126,9 @@ pub trait StateTransitionLike: /// Verifies an ECDSA signature with the public key fn verify_ecdsa_signature_by_public_key(&self, public_key: &[u8]) -> Result<(), ProtocolError> { if self.get_signature().is_empty() { - return Err(ProtocolError::StateTransitionIsNotIsSignedError { - state_transition: self.clone().into(), - }); + return Err(ProtocolError::StateTransitionIsNotSignedError( + StateTransitionIsNotSignedError::new(self.clone().into()), + )); } let data = self.to_buffer(true)?; Ok(signer::verify_data_signature( @@ -142,9 +145,9 @@ pub trait StateTransitionLike: bls: &T, ) -> Result<(), ProtocolError> { if self.get_signature().is_empty() { - return Err(ProtocolError::StateTransitionIsNotIsSignedError { - state_transition: self.clone().into(), - }); + return Err(ProtocolError::StateTransitionIsNotSignedError( + StateTransitionIsNotSignedError::new(self.clone().into()), + )); } let data = self.to_buffer(true)?; diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs index bb278eb96da..77c85d3a2ab 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs @@ -1,6 +1,12 @@ use anyhow::anyhow; use dashcore::secp256k1::{PublicKey as RawPublicKey, SecretKey as RawSecretKey}; +use crate::consensus::signature::InvalidSignaturePublicKeySecurityLevelError; +use crate::data_contract::state_transition::errors::PublicKeyIsDisabledError; +use crate::state_transition::errors::{ + InvalidIdentityPublicKeyTypeError, InvalidSignaturePublicKeyError, PublicKeyMismatchError, + PublicKeySecurityLevelNotMetError, StateTransitionIsNotSignedError, WrongPublicKeyPurposeError, +}; use crate::{ identity::{IdentityPublicKey, KeyID, KeyType, Purpose, SecurityLevel}, prelude::*, @@ -36,9 +42,9 @@ where // the compressed key stored in the identity if public_key_compressed.to_vec() != identity_public_key.data { - return Err(ProtocolError::InvalidSignaturePublicKeyError { - public_key: identity_public_key.data.to_owned(), - }); + return Err(ProtocolError::InvalidSignaturePublicKeyError( + InvalidSignaturePublicKeyError::new(identity_public_key.data.to_owned()), + )); } self.sign_by_private_key(private_key, identity_public_key.key_type, bls) @@ -48,9 +54,9 @@ where let pub_key_hash = ripemd160_sha256(&public_key_compressed); if pub_key_hash != identity_public_key.data { - return Err(ProtocolError::InvalidSignaturePublicKeyError { - public_key: identity_public_key.data.to_owned(), - }); + return Err(ProtocolError::InvalidSignaturePublicKeyError( + InvalidSignaturePublicKeyError::new(identity_public_key.data.to_owned()), + )); } self.sign_by_private_key(private_key, identity_public_key.key_type, bls) } @@ -58,9 +64,9 @@ where let public_key = bls.private_key_to_public_key(private_key)?; if public_key != identity_public_key.data { - return Err(ProtocolError::InvalidSignaturePublicKeyError { - public_key: identity_public_key.data.to_owned(), - }); + return Err(ProtocolError::InvalidSignaturePublicKeyError( + InvalidSignaturePublicKeyError::new(identity_public_key.data.to_owned()), + )); } self.sign_by_private_key(private_key, identity_public_key.key_type, bls) } @@ -68,9 +74,9 @@ where // the default behavior from // https://github.com/dashevo/platform/blob/6b02b26e5cd3a7c877c5fdfe40c4a4385a8dda15/packages/js-dpp/lib/stateTransition/AbstractStateTransitionIdentitySigned.js#L108 // is to return the error for the BIP13_SCRIPT_HASH - KeyType::BIP13_SCRIPT_HASH => Err(ProtocolError::InvalidIdentityPublicKeyTypeError { - public_key_type: identity_public_key.key_type, - }), + KeyType::BIP13_SCRIPT_HASH => Err(ProtocolError::InvalidIdentityPublicKeyTypeError( + InvalidIdentityPublicKeyTypeError::new(identity_public_key.key_type), + )), } } @@ -83,15 +89,15 @@ where let signature = self.get_signature(); if signature.is_empty() { - return Err(ProtocolError::StateTransitionIsNotIsSignedError { - state_transition: self.clone().into(), - }); + return Err(ProtocolError::StateTransitionIsNotSignedError( + StateTransitionIsNotSignedError::new(self.clone().into()), + )); } if self.get_signature_public_key_id() != Some(public_key.id) { - return Err(ProtocolError::PublicKeyMismatchError { - public_key: public_key.clone(), - }); + return Err(ProtocolError::PublicKeyMismatchError( + PublicKeyMismatchError::new(public_key.clone()), + )); } let public_key_bytes = public_key.data.as_slice(); @@ -119,25 +125,28 @@ where // a MASTER key if public_key.is_master() && self.get_security_level_requirement() != SecurityLevel::MASTER { - return Err(ProtocolError::InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level: public_key.security_level, - required_security_level: self.get_security_level_requirement(), - }); + return Err(ProtocolError::InvalidSignaturePublicKeySecurityLevelError( + InvalidSignaturePublicKeySecurityLevelError::new( + public_key.security_level, + self.get_security_level_requirement(), + ), + )); } // Otherwise, key security level should be less than MASTER but more or equal than required if self.get_security_level_requirement() < public_key.security_level { - return Err(ProtocolError::PublicKeySecurityLevelNotMetError { - public_key_security_level: public_key.security_level, - required_security_level: self.get_security_level_requirement(), - }); + return Err(ProtocolError::PublicKeySecurityLevelNotMetError( + PublicKeySecurityLevelNotMetError::new( + public_key.security_level, + self.get_security_level_requirement(), + ), + )); } if public_key.purpose != Purpose::AUTHENTICATION { - return Err(ProtocolError::WrongPublicKeyPurposeError { - public_key_purpose: public_key.purpose, - key_purpose_requirement: Purpose::AUTHENTICATION, - }); + return Err(ProtocolError::WrongPublicKeyPurposeError( + WrongPublicKeyPurposeError::new(public_key.purpose, Purpose::AUTHENTICATION), + )); } Ok(()) } @@ -147,9 +156,9 @@ where public_key: &IdentityPublicKey, ) -> Result<(), ProtocolError> { if public_key.disabled_at.is_some() { - return Err(ProtocolError::PublicKeyIsDisabledError { - public_key: public_key.to_owned(), - }); + return Err(ProtocolError::PublicKeyIsDisabledError( + PublicKeyIsDisabledError::new(public_key.to_owned()), + )); } Ok(()) } @@ -459,12 +468,9 @@ mod test { .sign(&keys.identity_public_key, &keys.ec_private, &bls) .unwrap_err(); match sign_error { - ProtocolError::PublicKeySecurityLevelNotMetError { - public_key_security_level: sec_level, - required_security_level: req_sec_level, - } => { - assert_eq!(SecurityLevel::MEDIUM, sec_level); - assert_eq!(SecurityLevel::HIGH, req_sec_level); + ProtocolError::PublicKeySecurityLevelNotMetError(err) => { + assert_eq!(SecurityLevel::MEDIUM, err.public_key_security_level()); + assert_eq!(SecurityLevel::HIGH, err.required_security_level()); } error => { panic!("invalid error type: {}", error) @@ -483,12 +489,9 @@ mod test { .sign(&keys.identity_public_key, &keys.ec_private, &bls) .unwrap_err(); match sign_error { - ProtocolError::WrongPublicKeyPurposeError { - public_key_purpose: purpose, - key_purpose_requirement: req_purpose, - } => { - assert_eq!(Purpose::ENCRYPTION, purpose); - assert_eq!(Purpose::AUTHENTICATION, req_purpose); + ProtocolError::WrongPublicKeyPurposeError(err) => { + assert_eq!(Purpose::ENCRYPTION, err.public_key_purpose()); + assert_eq!(Purpose::AUTHENTICATION, err.key_purpose_requirement()); } error => { panic!("invalid error type: {}", error) @@ -518,7 +521,7 @@ mod test { .verify_signature(&keys.identity_public_key, &bls) .unwrap_err(); match verify_error { - ProtocolError::StateTransitionIsNotIsSignedError { .. } => {} + ProtocolError::StateTransitionIsNotSignedError { .. } => {} error => { panic!("invalid error type: {}", error) } @@ -537,7 +540,7 @@ mod test { .verify_signature(&keys.identity_public_key, &bls) .unwrap_err(); match verify_error { - ProtocolError::StateTransitionIsNotIsSignedError { .. } => {} + ProtocolError::StateTransitionIsNotSignedError { .. } => {} error => { panic!("invalid error type: {}", error) } @@ -592,13 +595,15 @@ mod test { .sign(&keys.identity_public_key, &keys.bls_private, &bls) .expect_err("the protocol error should be returned"); - assert!(matches!( - result, - ProtocolError::InvalidSignaturePublicKeySecurityLevelError { public_key_security_level, required_security_level } if - { - public_key_security_level == SecurityLevel::MASTER && - required_security_level == SecurityLevel::HIGH + match result { + ProtocolError::InvalidSignaturePublicKeySecurityLevelError(err) => { + assert_eq!(err.public_key_security_level(), SecurityLevel::MASTER); + assert_eq!(err.required_key_security_level(), SecurityLevel::HIGH); } - )) + error => panic!( + "expected InvalidSignaturePublicKeySecurityLevelError, got {}", + error + ), + } } } diff --git a/packages/rs-dpp/src/state_transition/errors/invalid_identity_public_key_type_error.rs b/packages/rs-dpp/src/state_transition/errors/invalid_identity_public_key_type_error.rs new file mode 100644 index 00000000000..33dd2468da5 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/invalid_identity_public_key_type_error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::identity::KeyType; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid signature type")] +pub struct InvalidIdentityPublicKeyTypeError { + public_key_type: KeyType, +} + +impl InvalidIdentityPublicKeyTypeError { + pub fn new(public_key_type: KeyType) -> Self { + Self { public_key_type } + } + + pub fn public_key_type(&self) -> KeyType { + self.public_key_type.clone() + } +} + +impl From for ProtocolError { + fn from(err: InvalidIdentityPublicKeyTypeError) -> Self { + Self::InvalidIdentityPublicKeyTypeError(err) + } +} diff --git a/packages/rs-dpp/src/state_transition/errors/invalid_signature_public_key_error.rs b/packages/rs-dpp/src/state_transition/errors/invalid_signature_public_key_error.rs new file mode 100644 index 00000000000..9a4a60027d0 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/invalid_signature_public_key_error.rs @@ -0,0 +1,24 @@ +use crate::ProtocolError; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid signature public key")] +pub struct InvalidSignaturePublicKeyError { + public_key: Vec, +} + +impl InvalidSignaturePublicKeyError { + pub fn new(public_key: Vec) -> Self { + Self { public_key } + } + + pub fn public_key(&self) -> Vec { + self.public_key.clone() + } +} + +impl From for ProtocolError { + fn from(err: InvalidSignaturePublicKeyError) -> Self { + Self::InvalidSignaturePublicKeyError(err) + } +} diff --git a/packages/rs-dpp/src/state_transition/errors/mod.rs b/packages/rs-dpp/src/state_transition/errors/mod.rs new file mode 100644 index 00000000000..ab7d02480ad --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/mod.rs @@ -0,0 +1,13 @@ +mod invalid_identity_public_key_type_error; +mod invalid_signature_public_key_error; +mod public_key_mismatch_error; +mod public_key_security_level_not_met_error; +mod state_transition_is_not_signed_error; +mod wrong_public_key_purpose_error; + +pub use invalid_identity_public_key_type_error::*; +pub use invalid_signature_public_key_error::*; +pub use public_key_mismatch_error::*; +pub use public_key_security_level_not_met_error::*; +pub use state_transition_is_not_signed_error::*; +pub use wrong_public_key_purpose_error::*; diff --git a/packages/rs-dpp/src/state_transition/errors/public_key_mismatch_error.rs b/packages/rs-dpp/src/state_transition/errors/public_key_mismatch_error.rs new file mode 100644 index 00000000000..7716e98a963 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/public_key_mismatch_error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::identity::IdentityPublicKey; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Public key mismatched")] +pub struct PublicKeyMismatchError { + public_key: IdentityPublicKey, +} + +impl PublicKeyMismatchError { + pub fn new(public_key: IdentityPublicKey) -> Self { + Self { public_key } + } + + pub fn public_key(&self) -> IdentityPublicKey { + self.public_key.clone() + } +} + +impl From for ProtocolError { + fn from(err: PublicKeyMismatchError) -> Self { + Self::PublicKeyMismatchError(err) + } +} diff --git a/packages/rs-dpp/src/state_transition/errors/public_key_security_level_not_met_error.rs b/packages/rs-dpp/src/state_transition/errors/public_key_security_level_not_met_error.rs new file mode 100644 index 00000000000..c69caff4026 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/public_key_security_level_not_met_error.rs @@ -0,0 +1,36 @@ +use thiserror::Error; + +use crate::identity::SecurityLevel; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid key security level: {public_key_security_level}. The state transition requires at least: {required_security_level}")] +pub struct PublicKeySecurityLevelNotMetError { + public_key_security_level: SecurityLevel, + required_security_level: SecurityLevel, +} + +impl PublicKeySecurityLevelNotMetError { + pub fn new( + public_key_security_level: SecurityLevel, + required_security_level: SecurityLevel, + ) -> Self { + Self { + public_key_security_level, + required_security_level, + } + } + + pub fn public_key_security_level(&self) -> SecurityLevel { + self.public_key_security_level.clone() + } + pub fn required_security_level(&self) -> SecurityLevel { + self.required_security_level.clone() + } +} + +impl From for ProtocolError { + fn from(err: PublicKeySecurityLevelNotMetError) -> Self { + Self::PublicKeySecurityLevelNotMetError(err) + } +} diff --git a/packages/rs-dpp/src/state_transition/errors/state_transition_is_not_signed_error.rs b/packages/rs-dpp/src/state_transition/errors/state_transition_is_not_signed_error.rs new file mode 100644 index 00000000000..cc126cdb956 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/state_transition_is_not_signed_error.rs @@ -0,0 +1,26 @@ +use thiserror::Error; + +use crate::state_transition::StateTransition; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone)] +#[error("State Transition is not signed")] +pub struct StateTransitionIsNotSignedError { + state_transition: StateTransition, +} + +impl StateTransitionIsNotSignedError { + pub fn new(state_transition: StateTransition) -> Self { + Self { state_transition } + } + + pub fn state_transition(&self) -> StateTransition { + self.state_transition.clone() + } +} + +impl From for ProtocolError { + fn from(err: StateTransitionIsNotSignedError) -> Self { + Self::StateTransitionIsNotSignedError(err) + } +} diff --git a/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs b/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs new file mode 100644 index 00000000000..12f05a3f437 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs @@ -0,0 +1,33 @@ +use thiserror::Error; + +use crate::identity::Purpose; +use crate::ProtocolError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {key_purpose_requirement}")] +pub struct WrongPublicKeyPurposeError { + public_key_purpose: Purpose, + key_purpose_requirement: Purpose, +} + +impl WrongPublicKeyPurposeError { + pub fn new(public_key_purpose: Purpose, key_purpose_requirement: Purpose) -> Self { + Self { + public_key_purpose, + key_purpose_requirement, + } + } + + pub fn public_key_purpose(&self) -> Purpose { + self.public_key_purpose.clone() + } + pub fn key_purpose_requirement(&self) -> Purpose { + self.key_purpose_requirement.clone() + } +} + +impl From for ProtocolError { + fn from(err: WrongPublicKeyPurposeError) -> Self { + Self::WrongPublicKeyPurposeError(err) + } +} diff --git a/packages/rs-dpp/src/state_transition/mod.rs b/packages/rs-dpp/src/state_transition/mod.rs index 0954f625643..2bfecce8310 100644 --- a/packages/rs-dpp/src/state_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/mod.rs @@ -29,6 +29,7 @@ pub mod validation; pub mod fee; pub mod state_transition_execution_context; +pub mod errors; mod example; macro_rules! call_method { ($state_transition:expr, $method:ident, $args:tt ) => { diff --git a/packages/rs-dpp/src/state_transition/state_transition_factory.rs b/packages/rs-dpp/src/state_transition/state_transition_factory.rs index 321d63b52df..5bd3efefedd 100644 --- a/packages/rs-dpp/src/state_transition/state_transition_factory.rs +++ b/packages/rs-dpp/src/state_transition/state_transition_factory.rs @@ -1,6 +1,9 @@ use anyhow::anyhow; use std::convert::{TryFrom, TryInto}; +use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; +use crate::data_contract::errors::DataContractNotPresentError; +use crate::data_contract::state_transition::errors::MissingDataContractIdError; use crate::{ consensus::{basic::BasicError, ConsensusError}, data_contract::{ @@ -72,7 +75,9 @@ pub async fn create_state_transition( Ok(StateTransition::DocumentsBatch(documents_batch_transition)) } // TODO!! add basic validation - StateTransitionType::IdentityUpdate => Err(ProtocolError::InvalidStateTransitionTypeError), + StateTransitionType::IdentityUpdate => Err(ProtocolError::InvalidStateTransitionTypeError( + InvalidStateTransitionTypeError::new(transition_type as u8), + )), } } @@ -84,9 +89,9 @@ async fn fetch_data_contracts_for_document_transition( let mut data_contracts = vec![]; for transition in raw_document_transitions { let data_contract_id_bytes = transition.get_bytes("$dataContractId").map_err(|_| { - ProtocolError::MissingDataContractIdError { - raw_document_transition: transition.to_owned(), - } + ProtocolError::MissingDataContractIdError(MissingDataContractIdError::new( + transition.to_owned(), + )) })?; let data_contract_id = Identifier::from_bytes(&data_contract_id_bytes)?; @@ -96,7 +101,11 @@ async fn fetch_data_contracts_for_document_transition( .map(TryInto::try_into) .transpose() .map_err(Into::into)? - .ok_or(ProtocolError::DataContractNotPresentError { data_contract_id })?; + .ok_or_else(|| { + ProtocolError::DataContractNotPresentError(DataContractNotPresentError::new( + data_contract_id, + )) + })?; data_contracts.push(data_contract); } @@ -107,11 +116,14 @@ async fn fetch_data_contracts_for_document_transition( pub fn try_get_transition_type( raw_state_transition: &JsonValue, ) -> Result { - let transition_number = raw_state_transition + let transition_type = raw_state_transition .get_u64("type") .map_err(|_| missing_state_transition_error())?; - StateTransitionType::try_from(transition_number as u8) - .map_err(|_| ProtocolError::InvalidStateTransitionTypeError) + StateTransitionType::try_from(transition_type as u8).map_err(|_| { + ProtocolError::InvalidStateTransitionTypeError(InvalidStateTransitionTypeError::new( + transition_type as u8, + )) + }) } fn missing_state_transition_error() -> ProtocolError { @@ -226,9 +238,20 @@ mod test { }); let result = create_state_transition(&state_repostiory_mock, raw_state_transition).await; - assert!(matches!( - result, - Err(ProtocolError::InvalidStateTransitionTypeError) - )); + let err = get_protocol_error(result); + + match err { + ProtocolError::InvalidStateTransitionTypeError(err) => { + assert_eq!(err.transition_type(), 154); + } + _ => panic!("expected InvalidStateTransitionTypeError, got {}", err), + } + } + + pub fn get_protocol_error(result: Result) -> ProtocolError { + match result { + Ok(_) => panic!("expected to get ProtocolError, got valid result"), + Err(e) => e, + } } } diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index b32653ca600..1b77b2183cc 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -1,6 +1,9 @@ use anyhow::Context; use std::convert::TryInto; +use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; +use crate::data_contract::errors::IdentityNotPresentError; +use crate::state_transition::StateTransitionType; use crate::{ consensus::fee::FeeError, identity::{ @@ -73,7 +76,11 @@ where .map(TryInto::try_into) .transpose() .map_err(Into::into)? - .ok_or(ProtocolError::IdentityNotPresentError { id: *identity_id })?; + .ok_or_else(|| { + ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new( + identity_id.clone(), + )) + })?; if execution_context.is_dry_run() { return Ok(result); @@ -110,7 +117,11 @@ where balance } StateTransition::IdentityCreditWithdrawal(_) => { - return Err(ProtocolError::InvalidStateTransitionTypeError); + return Err(ProtocolError::InvalidStateTransitionTypeError( + InvalidStateTransitionTypeError::new( + StateTransitionType::IdentityCreditWithdrawal as u8, + ), + )); } }; @@ -139,7 +150,11 @@ where .map(TryInto::try_into) .transpose() .map_err(Into::into)? - .ok_or(ProtocolError::IdentityNotPresentError { id: *identity_id })?; + .ok_or_else(|| { + ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new( + identity_id.clone(), + )) + })?; Ok(identity.get_balance()) } @@ -379,9 +394,12 @@ mod test { .validate(&transition.into()) .await .expect_err("error should be returned"); - assert!(matches!( - result, - ProtocolError::InvalidStateTransitionTypeError - )) + + match result { + ProtocolError::InvalidStateTransitionTypeError(err) => { + assert_eq!(err.transition_type(), 6); + } + _ => panic!("expected InvalidStateTransitionTypeError, got {}", result), + } } } diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_identity_signature.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_identity_signature.rs index 108281a4bc9..cb414c28c99 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_identity_signature.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_identity_signature.rs @@ -3,6 +3,10 @@ use std::{collections::HashSet, convert::TryInto}; use anyhow::Context; use lazy_static::lazy_static; +use crate::consensus::signature::{ + IdentityNotFoundError, InvalidIdentityPublicKeyTypeError, MissingPublicKeyError, + PublicKeyIsDisabledError, PublicKeySecurityLevelNotMetError, +}; use crate::{ consensus::{signature::SignatureError, ConsensusError}, identity::KeyType, @@ -54,9 +58,9 @@ pub async fn validate_state_transition_identity_signature( let identity = match maybe_identity { Some(identity) => identity, None => { - validation_result.add_error(SignatureError::IdentityNotFoundError { - identity_id: state_transition.get_owner_id().to_owned(), - }); + validation_result.add_error(SignatureError::IdentityNotFoundError( + IdentityNotFoundError::new(state_transition.get_owner_id().to_owned()), + )); return Ok(validation_result); } }; @@ -69,18 +73,18 @@ pub async fn validate_state_transition_identity_signature( let public_key = match maybe_public_key { None => { - validation_result.add_error(SignatureError::MissingPublicKeyError { - public_key_id: signature_public_key_id, - }); + validation_result.add_error(SignatureError::MissingPublicKeyError( + MissingPublicKeyError::new(signature_public_key_id), + )); return Ok(validation_result); } Some(pk) => pk, }; if !SUPPORTED_KEY_TYPES.contains(&public_key.key_type) { - validation_result.add_error(SignatureError::InvalidIdentityPublicKeyTypeError { - public_key_type: public_key.key_type, - }); + validation_result.add_error(SignatureError::InvalidIdentityPublicKeyTypeError( + InvalidIdentityPublicKeyTypeError::new(public_key.key_type), + )); return Ok(validation_result); } @@ -108,34 +112,29 @@ fn convert_to_consensus_signature_error( error: ProtocolError, ) -> Result { match error { - ProtocolError::InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level, - required_security_level, - } => Ok(ConsensusError::SignatureError( - SignatureError::InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level, - required_key_security_level: required_security_level, - }, - )), - ProtocolError::PublicKeySecurityLevelNotMetError { - public_key_security_level, - required_security_level, - } => Ok(ConsensusError::SignatureError( - SignatureError::PublicKeySecurityLevelNotMetError { - public_key_security_level, - required_security_level, - }, - )), - ProtocolError::PublicKeyIsDisabledError { public_key } => Ok( - ConsensusError::SignatureError(SignatureError::PublicKeyIsDisabledError { - public_key_id: public_key.id, - }), - ), - ProtocolError::InvalidIdentityPublicKeyTypeError { public_key_type } => { + ProtocolError::InvalidSignaturePublicKeySecurityLevelError(err) => { Ok(ConsensusError::SignatureError( - SignatureError::InvalidIdentityPublicKeyTypeError { public_key_type }, + SignatureError::InvalidSignaturePublicKeySecurityLevelError(err), )) } + ProtocolError::PublicKeySecurityLevelNotMetError(err) => Ok( + ConsensusError::SignatureError(SignatureError::PublicKeySecurityLevelNotMetError( + PublicKeySecurityLevelNotMetError::new( + err.public_key_security_level(), + err.required_security_level(), + ), + )), + ), + ProtocolError::PublicKeyIsDisabledError(err) => Ok(ConsensusError::SignatureError( + SignatureError::PublicKeyIsDisabledError(PublicKeyIsDisabledError::new( + err.public_key().id, + )), + )), + ProtocolError::InvalidIdentityPublicKeyTypeError(err) => Ok( + ConsensusError::SignatureError(SignatureError::InvalidIdentityPublicKeyTypeError( + InvalidIdentityPublicKeyTypeError::new(err.public_key_type()), + )), + ), ProtocolError::Error(_) => Err(error), _ => Ok(ConsensusError::SignatureError( SignatureError::InvalidStateTransitionSignatureError, @@ -146,6 +145,8 @@ fn convert_to_consensus_signature_error( #[cfg(test)] mod test { use super::*; + use crate::consensus::signature::InvalidSignaturePublicKeySecurityLevelError; + use crate::state_transition::errors::{PublicKeyMismatchError, WrongPublicKeyPurposeError}; use crate::{ document::DocumentsBatchTransition, identity::{KeyID, Purpose, SecurityLevel}, @@ -162,6 +163,7 @@ mod test { NativeBlsModule, }; use serde::{Deserialize, Serialize}; + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct ExampleStateTransition { @@ -234,32 +236,35 @@ mod test { if let Some(error_num) = self.return_error { match error_num { 0 => { - return Err(ProtocolError::PublicKeyMismatchError { - public_key: public_key.clone(), - }) + return Err(ProtocolError::PublicKeyMismatchError( + PublicKeyMismatchError::new(public_key.clone()), + )) } 1 => { - return Err(ProtocolError::InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level: SecurityLevel::CRITICAL, - required_security_level: SecurityLevel::MASTER, - }) + return Err(ProtocolError::InvalidSignaturePublicKeySecurityLevelError( + InvalidSignaturePublicKeySecurityLevelError::new( + SecurityLevel::CRITICAL, + SecurityLevel::MASTER, + ), + )) } 2 => { - return Err(ProtocolError::PublicKeySecurityLevelNotMetError { - public_key_security_level: SecurityLevel::CRITICAL, - required_security_level: SecurityLevel::HIGH, - }) + return Err(ProtocolError::PublicKeySecurityLevelNotMetError( + crate::state_transition::errors::PublicKeySecurityLevelNotMetError::new( + SecurityLevel::CRITICAL, + SecurityLevel::HIGH, + ), + )) } 3 => { - return Err(ProtocolError::PublicKeyIsDisabledError { - public_key: public_key.clone(), - }) + return Err(ProtocolError::PublicKeyIsDisabledError( + crate::data_contract::state_transition::errors::PublicKeyIsDisabledError::new(public_key.clone()), + )) } 4 => { - return Err(ProtocolError::WrongPublicKeyPurposeError { - public_key_purpose: Purpose::WITHDRAW, - key_purpose_requirement: Purpose::DECRYPTION, - }) + return Err(ProtocolError::WrongPublicKeyPurposeError( + WrongPublicKeyPurposeError::new(Purpose::WITHDRAW, Purpose::DECRYPTION), + )) } _ => {} } @@ -341,11 +346,12 @@ mod test { .expect("the validation result should be returned"); let signature_error = get_signature_error_from_result(&result, 0); - assert!( - matches!(signature_error, SignatureError::IdentityNotFoundError { identity_id } if { - identity_id == identity.get_id() - }) - ); + match signature_error { + SignatureError::IdentityNotFoundError(err) => { + assert_eq!(err.identity_id(), identity.get_id().clone()) + } + error => panic!("expected IdentityNotFoundError, got {}", error), + } } #[tokio::test] @@ -373,11 +379,12 @@ mod test { .expect("the validation result should be returned"); let signature_error = get_signature_error_from_result(&result, 0); - assert!( - matches!(signature_error, SignatureError::MissingPublicKeyError { public_key_id } if { - *public_key_id == 12332 - }) - ); + match signature_error { + SignatureError::MissingPublicKeyError(err) => { + assert_eq!(err.public_key_id(), 12332) + } + error => panic!("expected MissingPublicKeyError, got {}", error), + } } #[tokio::test] @@ -389,7 +396,7 @@ mod test { let owner_id = identity.get_id(); let mut state_transition = get_mock_state_transition(); - state_transition.owner_id = *owner_id; + state_transition.owner_id = owner_id.clone(); state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); @@ -422,7 +429,7 @@ mod test { let owner_id = identity.get_id(); let mut state_transition = get_mock_state_transition(); - state_transition.owner_id = *owner_id; + state_transition.owner_id = owner_id.clone(); state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); @@ -452,7 +459,7 @@ mod test { let owner_id = identity.get_id(); let mut state_transition = get_mock_state_transition(); - state_transition.owner_id = *owner_id; + state_transition.owner_id = owner_id.clone(); state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); @@ -480,7 +487,7 @@ mod test { let owner_id = identity.get_id(); let mut state_transition = get_mock_state_transition(); - state_transition.owner_id = *owner_id; + state_transition.owner_id = owner_id.clone(); state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); @@ -511,7 +518,7 @@ mod test { let owner_id = identity.get_id(); let mut state_transition = get_mock_state_transition(); - state_transition.owner_id = *owner_id; + state_transition.owner_id = owner_id.clone(); state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_key_signature.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_key_signature.rs index 56c79fec42a..1b1d424cbd7 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_key_signature.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_key_signature.rs @@ -4,6 +4,8 @@ use anyhow::{bail, Context}; use async_trait::async_trait; use dashcore::signer::verify_hash_signature; +use crate::consensus::signature::IdentityNotFoundError; +use crate::consensus::ConsensusError; use crate::{ consensus::signature::SignatureError, identity::{ @@ -82,9 +84,11 @@ pub async fn validate_state_transition_key_signature( execution_context.add_operations(tmp_execution_context.get_operations()); if balance.is_none() { - result.add_error(SignatureError::IdentityNotFoundError { - identity_id: *target_identity_id, - }); + result.add_error(ConsensusError::SignatureError( + SignatureError::IdentityNotFoundError(IdentityNotFoundError::new( + *target_identity_id, + )), + )); return Ok(result); } } diff --git a/packages/rs-dpp/src/state_transition/validation/validator_transaction_basic.rs b/packages/rs-dpp/src/state_transition/validation/validator_transaction_basic.rs index c9e432ac20d..987cf117f54 100644 --- a/packages/rs-dpp/src/state_transition/validation/validator_transaction_basic.rs +++ b/packages/rs-dpp/src/state_transition/validation/validator_transaction_basic.rs @@ -5,6 +5,9 @@ use async_trait::async_trait; use mockall::{automock, predicate::*}; use serde_json::Value as JsonValue; +use crate::consensus::basic::state_transition::{ + InvalidStateTransitionTypeError, StateTransitionMaxSizeExceededError, +}; use crate::{ consensus::basic::BasicError, state_repository::StateRepositoryLike, @@ -32,9 +35,9 @@ async fn validate_state_transition_basic( let state_transition_type = match StateTransitionType::try_from(raw_transition_type) { Err(_) => { - result.add_error(BasicError::InvalidStateTransitionTypeError { - transition_type: raw_transition_type, - }); + result.add_error(BasicError::InvalidStateTransitionTypeError( + InvalidStateTransitionTypeError::new(raw_transition_type), + )); return Ok(result); } Ok(transition_type) => transition_type, @@ -54,10 +57,9 @@ async fn validate_state_transition_basic( payload, }) = state_transition.to_buffer(false) { - result.add_error(BasicError::StateTransitionMaxSizeExceededError { - actual_size_kbytes: payload.len() / 1024, - max_size_kbytes, - }); + result.add_error(BasicError::StateTransitionMaxSizeExceededError( + StateTransitionMaxSizeExceededError::new(payload.len() / 1024, max_size_kbytes), + )); } Ok(result) @@ -191,10 +193,15 @@ mod test { .expect("the validation result should be returned"); let basic_error = get_basic_error_from_result(&result, 0); - assert!(matches!( - basic_error, - BasicError::InvalidStateTransitionTypeError { transition_type } if { transition_type == &123} - )); + match basic_error { + BasicError::InvalidStateTransitionTypeError(err) => { + assert_eq!(err.transition_type(), 123) + } + _ => panic!( + "Expected InvalidStateTransitionTypeError, got {}", + basic_error + ), + } } #[tokio::test] @@ -219,10 +226,15 @@ mod test { .expect("the validation result should be returned"); let basic_error = get_basic_error_from_result(&result, 0); - assert!(matches!( - basic_error, - BasicError::InvalidStateTransitionTypeError { transition_type } if { transition_type == &123} - )); + match basic_error { + BasicError::InvalidStateTransitionTypeError(err) => { + assert_eq!(err.transition_type(), 123) + } + _ => panic!( + "Expected InvalidStateTransitionTypeError, got {}", + basic_error + ), + } } #[tokio::test] @@ -254,13 +266,16 @@ mod test { let basic_error = get_basic_error_from_result(&result, 0); - assert!(matches!( - basic_error, - BasicError::StateTransitionMaxSizeExceededError { actual_size_kbytes, max_size_kbytes} if { - *actual_size_kbytes == 53 && - *max_size_kbytes == 16 + match basic_error { + BasicError::StateTransitionMaxSizeExceededError(err) => { + assert_eq!(err.actual_size_kbytes(), 53); + assert_eq!(err.max_size_kbytes(), 16); } - )); + _ => panic!( + "Expected StateTransitionMaxSizeExceededError, got {}", + basic_error + ), + } } #[tokio::test] diff --git a/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic_spec.rs b/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic_spec.rs index 37db46cbce1..55257742c57 100644 --- a/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic_spec.rs +++ b/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_data_contract_update_transition_basic_spec.rs @@ -359,13 +359,17 @@ async fn should_have_existing_documents_schema_backward_compatible() { .expect("validation result should be returned"); let basic_error = get_basic_error_from_result(&result, 0); - assert!(matches!( - basic_error, - BasicError::IncompatibleDataContractSchemaError { operation, field_path, ..} if { - operation == "add" && - field_path == "/required/1" + + match basic_error { + BasicError::IncompatibleDataContractSchemaError(err) => { + assert_eq!(err.operation(), "add".to_string()); + assert_eq!(err.field_path(), "/required/1".to_string()); } - )); + _ => panic!( + "Expected IncompatibleDataContractSchemaError, got {}", + basic_error + ), + } } #[tokio::test] diff --git a/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs b/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs index af4fa45a2ca..f1ec29de4d4 100644 --- a/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs +++ b/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs @@ -96,10 +96,17 @@ fn should_return_invalid_result_if_some_of_unique_indices_have_changed() { assert_eq!(1053, result.errors()[0].code()); let basic_error = get_basic_error(&result, 0); - matches!(basic_error, BasicError::DataContractUniqueIndicesChangedError { document_type, index_name }if { - document_type == "indexedDocument" && - index_name == "index1" - }); + + match basic_error { + BasicError::DataContractUniqueIndicesChangedError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_name(), "index1".to_string()); + } + _ => panic!( + "Expected DataContractUniqueIndicesChangedError, got {}", + basic_error + ), + } } #[test] @@ -123,10 +130,17 @@ fn should_return_invalid_result_if_non_unique_index_update_failed_due_to_changed assert_eq!(0, result.errors()[0].code()); let basic_error = get_basic_error(&result, 0); - matches!(basic_error, BasicError::DataContractInvalidIndexDefinitionUpdateError { document_type, index_name }if { - document_type == "indexedDocument" && - index_name == "index3" - }); + + match basic_error { + BasicError::DataContractInvalidIndexDefinitionUpdateError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_name(), "index3".to_string()); + } + _ => panic!( + "Expected DataContractInvalidIndexDefinitionUpdateError, got {}", + basic_error + ), + } } #[test] @@ -151,10 +165,16 @@ fn should_return_invalid_result_if_already_indexed_properties_are_added_to_exist assert_eq!(0, result.errors()[0].code()); let basic_error = get_basic_error(&result, 0); - matches!(basic_error, BasicError::DataContractInvalidIndexDefinitionUpdateError { document_type, index_name }if { - document_type == "indexedDocument" && - index_name == "index3" - }); + match basic_error { + BasicError::DataContractInvalidIndexDefinitionUpdateError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_name(), "index3".to_string()); + } + _ => panic!( + "Expected DataContractInvalidIndexDefinitionUpdateError, got {}", + basic_error + ), + } } #[test] @@ -186,12 +206,19 @@ fn should_return_invalid_result_if_one_of_new_indices_contains_old_properties_in assert_eq!(0, result.errors()[0].code()); let basic_error = get_basic_error(&result, 0); + // the JS-version imports DataContractInvalidIndexDefinitionUpdateError as DataContractHaveNewIndexWithOldPropertiesError as // we should decide if we want to have a separate error called DataContractInvalidIndexDefinitionUpdateError - matches!(basic_error, BasicError::DataContractInvalidIndexDefinitionUpdateError { document_type, index_name }if { - document_type == "indexedDocument" && - index_name == "index_other" - }); + match basic_error { + BasicError::DataContractInvalidIndexDefinitionUpdateError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_name(), "index_other".to_string()); + } + _ => panic!( + "Expected DataContractInvalidIndexDefinitionUpdateError, got {}", + basic_error + ), + } } #[test] @@ -222,10 +249,17 @@ fn should_return_invalid_result_if_one_of_new_indices_is_unique() { assert_eq!(0, result.errors()[0].code()); let basic_error = get_basic_error(&result, 0); - matches!(basic_error, BasicError::DataContractHaveNewUniqueIndexError { document_type, index_name }if { - document_type == "indexedDocument" && - index_name == "index_other" - }); + + match basic_error { + BasicError::DataContractHaveNewUniqueIndexError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_name(), "index_other".to_string()); + } + _ => panic!( + "Expected DataContractHaveNewUniqueIndexError, got {}", + basic_error + ), + } } #[test] @@ -284,13 +318,15 @@ fn should_return_invalid_result_if_non_unique_index_added_for_non_indexed_proper assert_eq!(result.errors()[0].code(), 0); let basic_error = get_basic_error(&result, 0); - assert!(matches!( - basic_error, - BasicError::DataContractInvalidIndexDefinitionUpdateError { - document_type, - index_name, - } if { - document_type == "indexedDocument" && - index_name == "index1337" - })); + + match basic_error { + BasicError::DataContractInvalidIndexDefinitionUpdateError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_name(), "index1337".to_string()); + } + _ => panic!( + "Expected DataContractInvalidIndexDefinitionUpdateError, got {}", + basic_error + ), + } } diff --git a/packages/rs-dpp/src/tests/data_contract/validation/data_contract_validator_spec.rs b/packages/rs-dpp/src/tests/data_contract/validation/data_contract_validator_spec.rs index 27b535c687f..d8c7c211e78 100644 --- a/packages/rs-dpp/src/tests/data_contract/validation/data_contract_validator_spec.rs +++ b/packages/rs-dpp/src/tests/data_contract/validation/data_contract_validator_spec.rs @@ -1346,13 +1346,23 @@ mod documents { .expect("the error in result should exist"); assert_eq!(1009, pattern_error.get_code()); - assert!( - matches!(pattern_error, ConsensusError::IncompatibleRe2PatternError { path, pattern, .. } - if { - path == "/documents/indexedDocument/properties/something" && - pattern == "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$" - }) - ); + + match pattern_error { + ConsensusError::IncompatibleRe2PatternError(err) => { + assert_eq!( + err.path(), + "/documents/indexedDocument/properties/something".to_string() + ); + assert_eq!( + err.pattern(), + "^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$".to_string() + ); + } + _ => panic!( + "Expected IncompatibleRe2PatternError, got {:?}", + pattern_error + ), + } } } @@ -1600,10 +1610,12 @@ mod indices { .expect("the validation error should be returned"); let index_error = get_index_error(validation_error); - assert_eq!(1008, index_error.get_code()); - assert!( - matches!(index_error, IndexError::DuplicateIndexError { document_type, .. } if document_type == "indexedDocument") - ); + match index_error { + IndexError::DuplicateIndexError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + } + _ => panic!("Expected DuplicateIndexError, got {}", index_error), + } } #[test] @@ -1635,13 +1647,13 @@ mod indices { let basic_error = get_basic_error(validation_error); assert_eq!(1048, basic_error.get_code()); - assert!( - matches!(basic_error, BasicError::DuplicateIndexNameError { document_type, duplicate_index_name } - if { - document_type == "indexedDocument" && - duplicate_index_name == "index1" - }) - ); + match basic_error { + BasicError::DuplicateIndexNameError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.duplicate_index_name(), "index1".to_string()) + } + _ => panic!("Expected DuplicateIndexNameError, got {}", basic_error), + } } #[test] @@ -1956,13 +1968,17 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1017, index_error.get_code()); - assert!( - matches!(index_error, IndexError::UniqueIndicesLimitReachedError { document_type, index_limit } - if { - document_type == "indexedDocument" && - index_limit == &3 - }) - ); + match index_error { + IndexError::UniqueIndicesLimitReachedError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.index_limit(), 3); + // assert_eq!(err.property_type(), "array".to_string()); + } + _ => panic!( + "Expected UniqueIndicesLimitReachedError, got {}", + index_error + ), + } } #[test] @@ -1994,13 +2010,16 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1015, index_error.get_code()); - assert!( - matches!(index_error, IndexError::SystemPropertyIndexAlreadyPresentError { document_type, property_name, .. } - if { - document_type == "indexedDocument" && - property_name == "$id" - }) - ); + match index_error { + IndexError::SystemPropertyIndexAlreadyPresentError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.property_name(), "$id".to_string()); + } + _ => panic!( + "Expected SystemPropertyIndexAlreadyPresentError, got {}", + index_error + ), + } } #[test] @@ -2026,13 +2045,13 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1016, index_error.get_code()); - assert!( - matches!(index_error, IndexError::UndefinedIndexPropertyError { document_type, property_name, .. } - if { - document_type == "indexedDocument" && - property_name == "missingProperty" - }) - ); + match index_error { + IndexError::UndefinedIndexPropertyError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.property_name(), "missingProperty".to_string()); + } + _ => panic!("Expected UndefinedIndexPropertyError, got {}", index_error), + } } #[test] @@ -2073,14 +2092,17 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1013, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidIndexPropertyTypeError { document_type, property_name, property_type, ..} - if { - document_type == "indexedDocument" && - property_name == "objectProperty" && - property_type == "object" - }) - ); + match index_error { + IndexError::InvalidIndexPropertyTypeError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.property_name(), "objectProperty".to_string()); + assert_eq!(err.property_type(), "object".to_string()); + } + _ => panic!( + "Expected InvalidIndexPropertyTypeError, got {}", + index_error + ), + } } #[test] @@ -2125,14 +2147,17 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1013, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidIndexPropertyTypeError { document_type, property_name, property_type, ..} - if { - document_type == "indexedArray" && - property_name == "mentions" && - property_type == "array" - }) - ); + match index_error { + IndexError::InvalidIndexPropertyTypeError(err) => { + assert_eq!(err.document_type(), "indexedArray".to_string()); + assert_eq!(err.property_name(), "mentions".to_string()); + assert_eq!(err.property_type(), "array".to_string()); + } + _ => panic!( + "Expected InvalidIndexPropertyTypeError, got {}", + index_error + ), + } } // This section is originally commented out @@ -2332,14 +2357,17 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1013, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidIndexPropertyTypeError { document_type, property_name, property_type, ..} - if { - document_type == "indexedDocument" && - property_name == "arrayProperty" && - property_type == "array" - }) - ); + match index_error { + IndexError::InvalidIndexPropertyTypeError(err) => { + assert_eq!(err.document_type(), "indexedDocument".to_string()); + assert_eq!(err.property_name(), "arrayProperty"); + assert_eq!(err.property_type(), "array".to_string()); + } + _ => panic!( + "Expected InvalidIndexPropertyTypeError, got {}", + index_error + ), + } } #[test] @@ -2364,12 +2392,15 @@ mod indices { let index_error = get_index_error(error); assert_eq!(1010, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidCompoundIndexError { document_type, ..} - if { - document_type == "optionalUniqueIndexedDocument" - }) - ); + match index_error { + IndexError::InvalidCompoundIndexError(err) => { + assert_eq!( + err.document_type(), + "optionalUniqueIndexedDocument".to_string() + ); + } + _ => panic!("Expected InvalidCompoundIndexError, got {}", index_error), + } } #[test] @@ -2457,12 +2488,12 @@ mod indices { let index_error = get_index_error(&result.errors()[0]); assert_eq!(1016, index_error.get_code()); - assert!( - matches!(index_error, IndexError::UndefinedIndexPropertyError { property_name, ..} - if { - property_name == invalid_name - }) - ); + match index_error { + IndexError::UndefinedIndexPropertyError(err) => { + assert_eq!(err.property_name(), invalid_name.to_string()); + } + _ => panic!("Expected UndefinedIndexPropertyError, got {}", index_error), + } } } @@ -2738,12 +2769,15 @@ fn should_return_invalid_result_with_circular_ref_pointer() { let basic_error = get_basic_error(validation_error); assert_eq!(1014, validation_error.get_code()); - assert!( - matches!(basic_error, BasicError::InvalidJsonSchemaRefError { ref_error} - if { - ref_error == "the ref '#/$defs/object' contains cycles" - }) - ); + match basic_error { + BasicError::InvalidJsonSchemaRefError(err) => { + assert_eq!( + err.ref_error(), + "the ref '#/$defs/object' contains cycles".to_string() + ); + } + _ => panic!("Expected InvalidJsonSchemaRefError, got {}", basic_error), + } } #[test] @@ -2769,14 +2803,17 @@ fn should_return_invalid_result_if_indexed_string_property_missing_max_length_co let index_error = get_index_error(validation_error); assert_eq!(1012, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidIndexedPropertyConstraintError { property_name, constraint_name, reason, ..} - if { - property_name == "firstName" && - constraint_name == "maxLength" && - reason == "should be less or equal than 63" - }) - ); + match index_error { + IndexError::InvalidIndexedPropertyConstraintError(err) => { + assert_eq!(err.property_name(), "firstName".to_string()); + assert_eq!(err.constraint_name(), "maxLength".to_string()); + assert_eq!(err.reason(), "should be less or equal than 63".to_string()); + } + _ => panic!( + "Expected InvalidIndexedPropertyConstraintError, got {}", + index_error + ), + } } mod indexed_array { @@ -2870,14 +2907,17 @@ mod indexed_array { let index_error = get_index_error(validation_error); assert_eq!(1012, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidIndexedPropertyConstraintError { property_name, constraint_name, reason, ..} - if { - property_name == "byteArrayField" && - constraint_name == "maxItems" && - reason == "should be less or equal 255" - }) - ); + match index_error { + IndexError::InvalidIndexedPropertyConstraintError(err) => { + assert_eq!(err.property_name(), "byteArrayField".to_string()); + assert_eq!(err.constraint_name(), "maxItems".to_string()); + assert_eq!(err.reason(), "should be less or equal 255".to_string()); + } + _ => panic!( + "Expected InvalidIndexedPropertyConstraintError, got {}", + index_error + ), + } } #[test] @@ -2901,14 +2941,17 @@ mod indexed_array { let index_error = get_index_error(validation_error); assert_eq!(1012, index_error.get_code()); - assert!( - matches!(index_error, IndexError::InvalidIndexedPropertyConstraintError { property_name, constraint_name, reason, ..} - if { - property_name == "byteArrayField" && - constraint_name == "maxItems" && - reason == "should be less or equal 255" - }) - ); + match index_error { + IndexError::InvalidIndexedPropertyConstraintError(err) => { + assert_eq!(err.property_name(), "byteArrayField".to_string()); + assert_eq!(err.constraint_name(), "maxItems".to_string()); + assert_eq!(err.reason(), "should be less or equal 255".to_string()); + } + _ => panic!( + "Expected InvalidIndexedPropertyConstraintError, got {}", + index_error + ), + } } } diff --git a/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_documents_batch_transition_state_spec.rs b/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_documents_batch_transition_state_spec.rs index cbfd814d625..762ddeea054 100644 --- a/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_documents_batch_transition_state_spec.rs +++ b/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_documents_batch_transition_state_spec.rs @@ -134,11 +134,12 @@ async fn should_throw_error_if_data_contract_was_not_found() { .await .expect_err("protocol error expected"); - assert!(matches!( - error, - ProtocolError::DataContractNotPresentError { data_contract_id } if - data_contract_id == data_contract.id - )); + match error { + ProtocolError::DataContractNotPresentError(err) => { + assert_eq!(err.data_contract_id(), data_contract.id); + } + _ => panic!("Expected DataContractNotPresentError, got {}", error), + } } #[tokio::test] diff --git a/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_partial_compound_indices_spec.rs b/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_partial_compound_indices_spec.rs index 0fdd71fd171..6aaba2771ea 100644 --- a/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_partial_compound_indices_spec.rs +++ b/packages/rs-dpp/src/tests/document/state_transitions/validation/validate_partial_compound_indices_spec.rs @@ -59,12 +59,26 @@ fn should_return_invalid_result_if_compound_index_contains_not_all_fields() { assert!(!result.is_valid()); assert_eq!(1021, result.errors[0].code()); - assert!( - matches!(basic_error, BasicError::InconsistentCompoundIndexDataError { index_properties, document_type } if { - document_type == "optionalUniqueIndexedDocument" && - index_properties == &vec!["$ownerId".to_string(), "firstName".to_string(), "lastName".to_string()] - }) - ) + match basic_error { + BasicError::InconsistentCompoundIndexDataError(err) => { + assert_eq!( + err.document_type(), + "optionalUniqueIndexedDocument".to_string() + ); + assert_eq!( + err.index_properties(), + vec![ + "$ownerId".to_string(), + "firstName".to_string(), + "lastName".to_string() + ] + ); + } + _ => panic!( + "Expected InconsistentCompoundIndexDataError, got {}", + basic_error + ), + } } #[test] diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs index 599215919c6..ebce1b8479b 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs @@ -33,6 +33,7 @@ mod validate_identity_credit_withdrawal_transition_state_factory { use anyhow::Error; use crate::assert_consensus_errors; + use crate::consensus::signature::SignatureError; use crate::consensus::ConsensusError; use crate::prelude::{Identifier, Identity}; @@ -55,11 +56,21 @@ mod validate_identity_credit_withdrawal_transition_state_factory { .await .unwrap(); - assert_consensus_errors!(result, ConsensusError::BasicError, 1); - - let error = result.first_error().unwrap(); + let errors = result.errors(); + assert_eq!(errors.len(), 1); + let error = errors.first().unwrap(); assert_eq!(error.code(), 2000); + + match error { + ConsensusError::SignatureError(err) => match err { + SignatureError::IdentityNotFoundError(e) => { + assert_eq!(e.identity_id(), Identifier::default()); + } + e => panic!("expected IdentityNotFoundError, got {}", e), + }, + e => panic!("expected IdentityNotFoundError, got {:?}", e), + } } #[tokio::test] diff --git a/packages/rs-dpp/src/util/deserializer.rs b/packages/rs-dpp/src/util/deserializer.rs index b2ad7886bdf..6061e5fe05f 100644 --- a/packages/rs-dpp/src/util/deserializer.rs +++ b/packages/rs-dpp/src/util/deserializer.rs @@ -2,6 +2,7 @@ use anyhow::anyhow; use integer_encoding::VarInt; use serde_json::{Map, Number, Value as JsonValue}; +use crate::consensus::basic::decode::ProtocolVersionParsingError; use crate::data_contract::errors::StructureError; use crate::data_contract::extra::common::check_protocol_version; use crate::{errors::consensus::ConsensusError, errors::ProtocolError}; @@ -25,9 +26,9 @@ pub type ProtocolVersion = u32; pub fn get_protocol_version(version_bytes: &[u8]) -> Result { u32::decode_var(version_bytes) .ok_or_else(|| { - ConsensusError::ProtocolVersionParsingError { - parsing_error: anyhow!("length could not be decoded as a varint"), - } + ConsensusError::ProtocolVersionParsingError(ProtocolVersionParsingError::new(anyhow!( + "length could not be decoded as a varint" + ))) .into() }) .map(|(protocol_version, _size)| protocol_version) @@ -48,9 +49,9 @@ pub fn split_protocol_version( ) -> Result { let (protocol_version, protocol_version_size) = u32::decode_var(message_bytes).ok_or(ProtocolError::AbstractConsensusError(Box::new( - ConsensusError::ProtocolVersionParsingError { - parsing_error: anyhow!("length could not be decoded as a varint"), - }, + ConsensusError::ProtocolVersionParsingError(ProtocolVersionParsingError::new(anyhow!( + "length could not be decoded as a varint" + ))), )))?; let (_, main_message_bytes) = message_bytes.split_at(protocol_version_size); diff --git a/packages/wasm-dpp/src/data_contract/errors/invalid_document_type.rs b/packages/wasm-dpp/src/data_contract/errors/invalid_document_type.rs index d7855a06fb7..fa1cc261876 100644 --- a/packages/wasm-dpp/src/data_contract/errors/invalid_document_type.rs +++ b/packages/wasm-dpp/src/data_contract/errors/invalid_document_type.rs @@ -1,7 +1,7 @@ use thiserror::Error; use wasm_bindgen::prelude::*; -use crate::DataContractWasm; +use crate::identifier::IdentifierWrapper; #[wasm_bindgen] #[derive(Error, Debug)] @@ -9,16 +9,16 @@ use crate::DataContractWasm; pub struct InvalidDocumentTypeInDataContractError { // we have to store it as JsValue as the errors of 'class' Consensus are of different types doc_type: String, - data_contract: DataContractWasm, + data_contract_id: IdentifierWrapper, } #[wasm_bindgen] impl InvalidDocumentTypeInDataContractError { #[wasm_bindgen(constructor)] - pub fn new(doc_type: String, data_contract: DataContractWasm) -> Self { + pub fn new(doc_type: String, data_contract_id: IdentifierWrapper) -> Self { InvalidDocumentTypeInDataContractError { doc_type, - data_contract, + data_contract_id, } } #[wasm_bindgen(js_name = "getType")] @@ -27,7 +27,7 @@ impl InvalidDocumentTypeInDataContractError { } #[wasm_bindgen(js_name = "getDataContract")] - pub fn get_data_contract(&self) -> DataContractWasm { - self.data_contract.clone() + pub fn get_data_contract_id(&self) -> IdentifierWrapper { + self.data_contract_id.clone() } } diff --git a/packages/wasm-dpp/src/data_contract/errors/mod.rs b/packages/wasm-dpp/src/data_contract/errors/mod.rs index aef56e812d7..23b427f5d7f 100644 --- a/packages/wasm-dpp/src/data_contract/errors/mod.rs +++ b/packages/wasm-dpp/src/data_contract/errors/mod.rs @@ -19,14 +19,13 @@ pub fn from_data_contract_to_js_error(e: DataContractError) -> JsValue { .expect("statically known structure should be a valid JSON"), ) .into(), - DataContractError::InvalidDocumentTypeError { - doc_type, - data_contract, - } => invalid_document_type::InvalidDocumentTypeInDataContractError::new( - doc_type, - data_contract.into(), - ) - .into(), + DataContractError::InvalidDocumentTypeError(err) => { + invalid_document_type::InvalidDocumentTypeInDataContractError::new( + err.document_type(), + err.data_contract_id().into(), + ) + .into() + } _ => todo!(), } } diff --git a/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs b/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs index 7d11db2ba02..31139f53a71 100644 --- a/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs +++ b/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs @@ -139,8 +139,8 @@ impl DataContractFactoryWasm { .await; match result { Ok(data_contract) => Ok(data_contract.into()), - Err(dpp::ProtocolError::InvalidDataContractError { errors, .. }) => { - Err(InvalidDataContractError::new(errors, object).into()) + Err(dpp::ProtocolError::InvalidDataContractError(err)) => { + Err(InvalidDataContractError::new(err.errors, object).into()) } Err(other) => Err(from_dpp_err(other)), } diff --git a/packages/wasm-dpp/src/errors/consensus/basic/document/missing_data_contract_id_error.rs b/packages/wasm-dpp/src/errors/consensus/basic/document/missing_data_contract_id_error.rs index 9836f455f4b..8b252552119 100644 --- a/packages/wasm-dpp/src/errors/consensus/basic/document/missing_data_contract_id_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/basic/document/missing_data_contract_id_error.rs @@ -1,13 +1,19 @@ +use dpp::document::document_transition::document_base_transition::JsonValue; +use serde::Serialize; use wasm_bindgen::prelude::*; #[wasm_bindgen(js_name=MissingDataContractIdError)] pub struct MissingDataContractIdErrorWasm { + raw_document_transition: JsonValue, code: u32, } impl MissingDataContractIdErrorWasm { - pub fn new(code: u32) -> Self { - MissingDataContractIdErrorWasm { code } + pub fn new(raw_document_transition: JsonValue, code: u32) -> Self { + MissingDataContractIdErrorWasm { + raw_document_transition, + code, + } } } @@ -17,4 +23,12 @@ impl MissingDataContractIdErrorWasm { pub fn get_code(&self) -> u32 { self.code } + + #[wasm_bindgen(js_name=rawDocumentTransition)] + pub fn raw_document_transition(&self) -> wasm_bindgen::JsValue { + let serializer = serde_wasm_bindgen::Serializer::json_compatible(); + self.raw_document_transition + .serialize(&serializer) + .expect("implements Serialize") + } } diff --git a/packages/wasm-dpp/src/errors/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus_error.rs index 0365ce06671..96a5ff88cb5 100644 --- a/packages/wasm-dpp/src/errors/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus_error.rs @@ -171,24 +171,17 @@ pub fn from_consensus_error_ref(e: &DPPConsensusError) -> JsValue { ) .into() } - DPPConsensusError::ProtocolVersionParsingError { parsing_error } => { + DPPConsensusError::ProtocolVersionParsingError(err) => { ProtocolVersionParsingErrorWasm::new( - wasm_bindgen::JsError::new(parsing_error.to_string().as_ref()), + wasm_bindgen::JsError::new(err.parsing_error.to_string().as_ref()), code, ) .into() } - DPPConsensusError::IncompatibleRe2PatternError { - pattern, - path, - message, - } => IncompatibleRe2PatternErrorWasm::new( - pattern.clone(), - path.clone(), - message.clone(), - code, - ) - .into(), + DPPConsensusError::IncompatibleRe2PatternError(err) => { + IncompatibleRe2PatternErrorWasm::new(err.pattern(), err.path(), err.message(), code) + .into() + } DPPConsensusError::FeeError(e) => match e { dpp::consensus::fee::FeeError::BalanceIsNotEnoughError { balance, fee } => { BalanceIsNotEnoughErrorWasm::new(*balance, *fee, code).into() @@ -344,116 +337,96 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::DataContractNotPresent { data_contract_id } => { DataContractNotPresentErrorWasm::new(*data_contract_id, code).into() } - BasicError::InvalidDataContractVersionError { - expected_version, - version, - } => InvalidDataContractVersionErrorWasm::new(*expected_version, *version, code).into(), + BasicError::InvalidDataContractVersionError(err) => { + InvalidDataContractVersionErrorWasm::new(err.expected_version(), err.version(), code) + .into() + } BasicError::DataContractMaxDepthExceedError(depth) => { DataContractMaxDepthExceedErrorWasm::new(*depth, code).into() } - BasicError::InvalidDocumentTypeError { - document_type, - data_contract_id, - } => { - InvalidDocumentTypeErrorWasm::new(document_type.clone(), *data_contract_id, code).into() - } - BasicError::DuplicateIndexNameError { - document_type, - duplicate_index_name, - } => DuplicateIndexNameErrorWasm::new( - document_type.clone(), - duplicate_index_name.clone(), - code, - ) - .into(), - BasicError::InvalidJsonSchemaRefError { ref_error } => { - InvalidJsonSchemaRefErrorWasm::new(ref_error.clone(), code).into() + BasicError::InvalidDocumentTypeError(err) => { + InvalidDocumentTypeErrorWasm::new(err.document_type(), err.data_contract_id(), code) + .into() + } + BasicError::DuplicateIndexNameError(err) => { + DuplicateIndexNameErrorWasm::new(err.document_type(), err.duplicate_index_name(), code) + .into() + } + BasicError::InvalidJsonSchemaRefError(err) => { + InvalidJsonSchemaRefErrorWasm::new(err.ref_error(), code).into() } BasicError::IndexError(index_error) => match index_error { - dpp::consensus::basic::IndexError::UniqueIndicesLimitReachedError { - document_type, - index_limit, - } => UniqueIndicesLimitReachedErrorWasm::new(document_type.clone(), *index_limit, code) - .into(), - dpp::consensus::basic::IndexError::SystemPropertyIndexAlreadyPresentError { - document_type, - index_definition, - property_name, - } => SystemPropertyIndexAlreadyPresentErrorWasm::new( - document_type.clone(), - index_definition.clone(), - property_name.clone(), - code, - ) - .into(), - dpp::consensus::basic::IndexError::UndefinedIndexPropertyError { - document_type, - index_definition, - property_name, - } => UndefinedIndexPropertyErrorWasm::new( - document_type.clone(), - index_definition.clone(), - property_name.clone(), - code, - ) - .into(), - dpp::consensus::basic::IndexError::InvalidIndexPropertyTypeError { - document_type, - index_definition, - property_name, - property_type, - } => InvalidIndexPropertyTypeErrorWasm::new( - document_type.clone(), - index_definition.clone(), - property_name.clone(), - property_type.clone(), - code, - ) - .into(), - dpp::consensus::basic::IndexError::InvalidIndexedPropertyConstraintError { - document_type, - index_definition, - property_name, - constraint_name, - reason, - } => InvalidIndexedPropertyConstraintErrorWasm::new( - document_type.clone(), - index_definition.clone(), - property_name.clone(), - constraint_name.clone(), - reason.clone(), - code, - ) - .into(), - dpp::consensus::basic::IndexError::InvalidCompoundIndexError { - document_type, - index_definition, - } => InvalidCompoundIndexErrorWasm::new( - document_type.clone(), - index_definition.clone(), - code, - ) - .into(), - dpp::consensus::basic::IndexError::DuplicateIndexError { - document_type, - index_definition, - } => { - DuplicateIndexErrorWasm::new(document_type.clone(), index_definition.clone(), code) + dpp::consensus::basic::IndexError::UniqueIndicesLimitReachedError(err) => { + UniqueIndicesLimitReachedErrorWasm::new( + err.document_type(), + err.index_limit(), + code, + ) + .into() + } + dpp::consensus::basic::IndexError::SystemPropertyIndexAlreadyPresentError(err) => { + SystemPropertyIndexAlreadyPresentErrorWasm::new( + err.document_type(), + err.index_definition(), + err.property_name(), + code, + ) + .into() + } + dpp::consensus::basic::IndexError::UndefinedIndexPropertyError(err) => { + UndefinedIndexPropertyErrorWasm::new( + err.document_type(), + err.index_definition(), + err.property_name(), + code, + ) + .into() + } + dpp::consensus::basic::IndexError::InvalidIndexPropertyTypeError(err) => { + InvalidIndexPropertyTypeErrorWasm::new( + err.document_type(), + err.index_definition(), + err.property_name(), + err.property_type(), + code, + ) + .into() + } + dpp::consensus::basic::IndexError::InvalidIndexedPropertyConstraintError(err) => { + InvalidIndexedPropertyConstraintErrorWasm::new( + err.document_type(), + err.index_definition(), + err.property_name(), + err.constraint_name(), + err.reason(), + code, + ) + .into() + } + dpp::consensus::basic::IndexError::InvalidCompoundIndexError(err) => { + InvalidCompoundIndexErrorWasm::new( + err.document_type(), + err.index_definition(), + code, + ) + .into() + } + dpp::consensus::basic::IndexError::DuplicateIndexError(err) => { + DuplicateIndexErrorWasm::new(err.document_type(), err.index_definition(), code) .into() } }, BasicError::JsonSchemaCompilationError(error) => { JsonSchemaCompilationErrorWasm::new(error.clone(), code).into() } - BasicError::InconsistentCompoundIndexDataError { - index_properties, - document_type, - } => InconsistentCompoundIndexDataErrorWasm::new( - index_properties.clone(), - document_type.clone(), - code, - ) - .into(), + BasicError::InconsistentCompoundIndexDataError(err) => { + InconsistentCompoundIndexDataErrorWasm::new( + err.index_properties(), + err.document_type(), + code, + ) + .into() + } BasicError::MissingDocumentTransitionTypeError => { MissingDocumentTransitionTypeErrorWasm::new(code).into() } @@ -462,101 +435,88 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { MissingDocumentTransitionActionErrorWasm::new(code).into() } - BasicError::InvalidDocumentTransitionActionError { action } => { - InvalidDocumentTransitionActionErrorWasm::new(action.clone(), code).into() - } - BasicError::InvalidDocumentTransitionIdError { - expected_id, - invalid_id, - } => InvalidDocumentTransitionIdErrorWasm::new(*expected_id, *invalid_id, code).into(), - BasicError::DuplicateDocumentTransitionsWithIndicesError { references } => { - DuplicateDocumentTransitionsWithIndicesErrorWasm::new(references.clone(), code).into() - } - BasicError::DuplicateDocumentTransitionsWithIdsError { references } => { - DuplicateDocumentTransitionsWithIdsErrorWasm::new(references.clone(), code).into() - } - BasicError::MissingDataContractIdError => MissingDataContractIdErrorWasm::new(code).into(), - BasicError::InvalidIdentifierError { - identifier_name, - error, - } => InvalidIdentifierErrorWasm::new(identifier_name.clone(), error.clone(), code).into(), - BasicError::DataContractUniqueIndicesChangedError { - document_type, - index_name, - } => DataContractUniqueIndicesChangedErrorWasm::new( - document_type.clone(), - index_name.clone(), - code, - ) - .into(), - BasicError::DataContractInvalidIndexDefinitionUpdateError { - document_type, - index_name, - } => DataContractInvalidIndexDefinitionUpdateErrorWasm::new( - document_type.clone(), - index_name.clone(), - code, - ) - .into(), - BasicError::DataContractHaveNewUniqueIndexError { - document_type, - index_name, - } => DataContractHaveNewUniqueIndexErrorWasm::new( - document_type.clone(), - index_name.clone(), - code, - ) - .into(), - BasicError::IdentityNotFoundError { identity_id } => { - IdentityNotFoundErrorWasm::new(*identity_id, code).into() + BasicError::InvalidDocumentTransitionActionError(err) => { + InvalidDocumentTransitionActionErrorWasm::new(err.action(), code).into() + } + BasicError::InvalidDocumentTransitionIdError(err) => { + InvalidDocumentTransitionIdErrorWasm::new(err.expected_id(), err.invalid_id(), code) + .into() + } + BasicError::DuplicateDocumentTransitionsWithIndicesError(err) => { + DuplicateDocumentTransitionsWithIndicesErrorWasm::new(err.references(), code).into() + } + BasicError::DuplicateDocumentTransitionsWithIdsError(err) => { + DuplicateDocumentTransitionsWithIdsErrorWasm::new(err.references(), code).into() + } + BasicError::MissingDataContractIdError(err) => { + MissingDataContractIdErrorWasm::new(err.raw_document_transition(), code).into() + } + BasicError::InvalidIdentifierError(err) => { + InvalidIdentifierErrorWasm::new(err.identifier_name(), err.error(), code).into() + } + BasicError::DataContractUniqueIndicesChangedError(err) => { + DataContractUniqueIndicesChangedErrorWasm::new( + err.document_type(), + err.index_name(), + code, + ) + .into() + } + BasicError::DataContractInvalidIndexDefinitionUpdateError(err) => { + DataContractInvalidIndexDefinitionUpdateErrorWasm::new( + err.document_type(), + err.index_name(), + code, + ) + .into() + } + BasicError::DataContractHaveNewUniqueIndexError(err) => { + DataContractHaveNewUniqueIndexErrorWasm::new( + err.document_type(), + err.index_name(), + code, + ) + .into() } BasicError::MissingStateTransitionTypeError => { MissingStateTransitionTypeErrorWasm::new(code).into() } - BasicError::InvalidStateTransitionTypeError { transition_type } => { - InvalidStateTransitionTypeErrorWasm::new(*transition_type, code).into() + BasicError::InvalidStateTransitionTypeError(err) => { + InvalidStateTransitionTypeErrorWasm::new(err.transition_type(), code).into() } - BasicError::StateTransitionMaxSizeExceededError { - actual_size_kbytes, - max_size_kbytes, - } => StateTransitionMaxSizeExceededErrorWasm::new( - *actual_size_kbytes, - *max_size_kbytes, - code, - ) - .into(), - BasicError::DataContractImmutablePropertiesUpdateError { - operation, - field_path, - } => DataContractImmutablePropertiesUpdateErrorWasm::new( - operation.clone(), - field_path.clone(), - code, - ) - .into(), - BasicError::IncompatibleDataContractSchemaError { - data_contract_id, - operation, - field_path, - old_schema, - new_schema, - } => IncompatibleDataContractSchemaErrorWasm::new( - *data_contract_id, - operation.clone(), - field_path.clone(), - old_schema.clone(), - new_schema.clone(), - code, - ) - .into(), - BasicError::InvalidIdentityKeySignatureError { public_key_id } => { - InvalidIdentityKeySignatureErrorWasm::new(*public_key_id, code).into() + BasicError::StateTransitionMaxSizeExceededError(err) => { + StateTransitionMaxSizeExceededErrorWasm::new( + err.actual_size_kbytes(), + err.max_size_kbytes(), + code, + ) + .into() + } + BasicError::DataContractImmutablePropertiesUpdateError(err) => { + DataContractImmutablePropertiesUpdateErrorWasm::new( + err.operation(), + err.field_path(), + code, + ) + .into() + } + BasicError::IncompatibleDataContractSchemaError(err) => { + IncompatibleDataContractSchemaErrorWasm::new( + err.data_contract_id(), + err.operation(), + err.field_path(), + err.old_schema(), + err.new_schema(), + code, + ) + .into() + } + BasicError::InvalidIdentityKeySignatureError(err) => { + InvalidIdentityKeySignatureErrorWasm::new(err.public_key_id(), code).into() + } + BasicError::InvalidDataContractIdError(err) => { + InvalidDataContractIdErrorWasm::new(err.expected_id(), err.invalid_id(), code).into() } - BasicError::InvalidDataContractIdError { - expected_id, - invalid_id, - } => InvalidDataContractIdErrorWasm::new(expected_id.clone(), invalid_id.clone(), code) - .into(), } } @@ -564,46 +524,43 @@ fn from_signature_error(signature_error: &SignatureError) -> JsValue { let code = signature_error.get_code(); match signature_error.deref() { - SignatureError::MissingPublicKeyError { public_key_id } => { - MissingPublicKeyErrorWasm::new(*public_key_id, code).into() + SignatureError::MissingPublicKeyError(err) => { + MissingPublicKeyErrorWasm::new(err.public_key_id(), code).into() } - SignatureError::InvalidIdentityPublicKeyTypeError { public_key_type } => { - InvalidIdentityPublicKeyTypeErrorWasm::new(*public_key_type, code).into() + SignatureError::InvalidIdentityPublicKeyTypeError(err) => { + InvalidIdentityPublicKeyTypeErrorWasm::new(err.public_key_type(), code).into() } SignatureError::InvalidStateTransitionSignatureError => { InvalidStateTransitionSignatureErrorWasm::new(code).into() } - SignatureError::IdentityNotFoundError { identity_id } => { - IdentityNotFoundErrorWasm::new(*identity_id, code).into() + SignatureError::IdentityNotFoundError(err) => { + IdentityNotFoundErrorWasm::new(err.identity_id(), code).into() } - SignatureError::InvalidSignaturePublicKeySecurityLevelError { - public_key_security_level, - required_key_security_level, - } => InvalidSignaturePublicKeySecurityLevelErrorWasm::new( - *public_key_security_level, - *required_key_security_level, - code, - ) - .into(), - SignatureError::PublicKeyIsDisabledError { public_key_id } => { - PublicKeyIsDisabledErrorWasm::new(*public_key_id, code).into() - } - SignatureError::PublicKeySecurityLevelNotMetError { - public_key_security_level, - required_security_level, - } => PublicKeySecurityLevelNotMetErrorWasm::new( - *public_key_security_level, - *required_security_level, + SignatureError::InvalidSignaturePublicKeySecurityLevelError(err) => { + InvalidSignaturePublicKeySecurityLevelErrorWasm::new( + err.public_key_security_level(), + err.required_key_security_level(), + code, + ) + .into() + } + SignatureError::PublicKeyIsDisabledError(err) => { + PublicKeyIsDisabledErrorWasm::new(err.public_key_id(), code).into() + } + SignatureError::PublicKeySecurityLevelNotMetError(err) => { + PublicKeySecurityLevelNotMetErrorWasm::new( + err.public_key_security_level(), + err.required_security_level(), + code, + ) + .into() + } + SignatureError::WrongPublicKeyPurposeError(err) => WrongPublicKeyPurposeErrorWasm::new( + err.public_key_purpose(), + err.key_purpose_requirement(), code, ) .into(), - SignatureError::WrongPublicKeyPurposeError { - public_key_purpose, - key_purpose_requirement, - } => { - WrongPublicKeyPurposeErrorWasm::new(*public_key_purpose, *key_purpose_requirement, code) - .into() - } } } diff --git a/packages/wasm-dpp/src/errors/from.rs b/packages/wasm-dpp/src/errors/from.rs index c913db2d259..46ccf56f41e 100644 --- a/packages/wasm-dpp/src/errors/from.rs +++ b/packages/wasm-dpp/src/errors/from.rs @@ -1,3 +1,4 @@ +use dpp::data_contract::errors::DataContractNotPresentError; use wasm_bindgen::JsValue; use dpp::errors::ProtocolError; @@ -25,8 +26,8 @@ pub fn from_dpp_err(pe: ProtocolError) -> JsValue { ) .into(), - ProtocolError::DataContractNotPresentError { data_contract_id } => { - DataContractNotPresentNotConsensusErrorWasm::new(data_contract_id).into() + ProtocolError::DataContractNotPresentError(err) => { + DataContractNotPresentNotConsensusErrorWasm::new(err.data_contract_id()).into() } _ => JsValue::from_str(&format!("Error conversion not implemented: {pe:#}",)), } diff --git a/packages/wasm-dpp/src/errors/protocol_error.rs b/packages/wasm-dpp/src/errors/protocol_error.rs index 9417799df1c..6a0b72d3ad8 100644 --- a/packages/wasm-dpp/src/errors/protocol_error.rs +++ b/packages/wasm-dpp/src/errors/protocol_error.rs @@ -8,13 +8,11 @@ pub fn from_protocol_error(protocol_error: dpp::ProtocolError) -> JsValue { dpp::ProtocolError::AbstractConsensusError(consensus_error) => { from_consensus_error(*consensus_error) } - dpp::ProtocolError::InvalidDataContractError { - errors, - raw_data_contract, - } => { + dpp::ProtocolError::InvalidDataContractError(err) => { + let raw_data_contract = err.raw_data_contract(); let protocol = serde_wasm_bindgen::to_value(&raw_data_contract); protocol.map_or_else(JsValue::from, |raw_contract| { - InvalidDataContractError::new(errors, raw_contract).into() + InvalidDataContractError::new(err.errors, raw_contract).into() }) } dpp::ProtocolError::Error(anyhow_error) => { diff --git a/packages/wasm-dpp/src/identifier/mod.rs b/packages/wasm-dpp/src/identifier/mod.rs index f37e7f48ea4..d55a87f0ca3 100644 --- a/packages/wasm-dpp/src/identifier/mod.rs +++ b/packages/wasm-dpp/src/identifier/mod.rs @@ -27,7 +27,7 @@ extern "C" { fn log(a: &str); } -#[derive(Clone)] +#[derive(Clone, Debug)] #[wasm_bindgen(js_name=Identifier, inspectable)] pub struct IdentifierWrapper { wrapped: identifier::Identifier,