dpp/data_contract/methods/validate_document/v0/
mod.rs

1use crate::data_contract::accessors::v0::DataContractV0Getters;
2use crate::data_contract::document_type::accessors::DocumentTypeV0Getters;
3use crate::data_contract::document_type::DocumentType;
4
5use crate::consensus::basic::document::{
6    DocumentFieldMaxSizeExceededError, InvalidDocumentTypeError,
7};
8use crate::consensus::basic::BasicError;
9use crate::consensus::ConsensusError;
10use crate::data_contract::schema::DataContractSchemaMethodsV0;
11use crate::data_contract::DataContract;
12use crate::document::{Document, DocumentV0Getters};
13use crate::validation::SimpleConsensusValidationResult;
14use crate::ProtocolError;
15use platform_value::Value;
16use platform_version::version::PlatformVersion;
17use std::ops::Deref;
18
19pub trait DataContractDocumentValidationMethodsV0 {
20    fn validate_document(
21        &self,
22        name: &str,
23        document: &Document,
24        platform_version: &PlatformVersion,
25    ) -> Result<SimpleConsensusValidationResult, ProtocolError>;
26
27    fn validate_document_properties(
28        &self,
29        name: &str,
30        value: Value,
31        platform_version: &PlatformVersion,
32    ) -> Result<SimpleConsensusValidationResult, ProtocolError>;
33}
34
35impl DataContract {
36    #[inline(always)]
37    pub(super) fn validate_document_properties_v0(
38        &self,
39        name: &str,
40        value: Value,
41        platform_version: &PlatformVersion,
42    ) -> Result<SimpleConsensusValidationResult, ProtocolError> {
43        let Some(document_type) = self.document_type_optional_for_name(name) else {
44            return Ok(SimpleConsensusValidationResult::new_with_error(
45                InvalidDocumentTypeError::new(name.to_owned(), self.id()).into(),
46            ));
47        };
48
49        let validator = document_type.json_schema_validator_ref().deref();
50
51        if let Some((key, size)) =
52            value.has_data_larger_than(platform_version.system_limits.max_field_value_size)
53        {
54            let field = match key {
55                Some(Value::Text(field)) => field,
56                _ => "".to_string(),
57            };
58            return Ok(SimpleConsensusValidationResult::new_with_error(
59                ConsensusError::BasicError(BasicError::DocumentFieldMaxSizeExceededError(
60                    DocumentFieldMaxSizeExceededError::new(
61                        field,
62                        size as u64,
63                        platform_version.system_limits.max_field_value_size as u64,
64                    ),
65                )),
66            ));
67        }
68
69        let json_value = match value.try_into_validating_json() {
70            Ok(json_value) => json_value,
71            Err(e) => {
72                return Ok(SimpleConsensusValidationResult::new_with_error(
73                    ConsensusError::BasicError(BasicError::ValueError(e.into())),
74                ))
75            }
76        };
77
78        // Compile json schema validator if it's not yet compiled
79        if !validator.is_compiled(platform_version)? {
80            // It is normal that we get a protocol error here, since the document type is coming
81            // from the state
82            let root_schema = DocumentType::enrich_with_base_schema(
83                // TODO: I just wondering if we could you references here
84                //  instead of cloning
85                document_type.schema().clone(),
86                self.schema_defs().map(|defs| Value::from(defs.clone())),
87                platform_version,
88            )?;
89
90            let root_json_schema = root_schema
91                .try_to_validating_json()
92                .map_err(ProtocolError::ValueError)?;
93
94            validator.compile_and_validate(&root_json_schema, &json_value, platform_version)
95        } else {
96            validator.validate(&json_value, platform_version)
97        }
98    }
99
100    #[inline(always)]
101    pub(super) fn validate_document_v0(
102        &self,
103        name: &str,
104        document: &Document,
105        platform_version: &PlatformVersion,
106    ) -> Result<SimpleConsensusValidationResult, ProtocolError> {
107        // Validate user defined properties
108        self.validate_document_properties_v0(name, document.properties().into(), platform_version)
109    }
110}