dpp/document/specialized_document_factory/
mod.rs

1mod v0;
2
3use crate::data_contract::DataContract;
4use std::collections::BTreeMap;
5
6use crate::version::PlatformVersion;
7use crate::ProtocolError;
8use derive_more::From;
9use platform_value::{Bytes32, Identifier, Value};
10
11use crate::data_contract::document_type::DocumentTypeRef;
12use crate::document::Document;
13#[cfg(feature = "extended-document")]
14use crate::document::ExtendedDocument;
15#[cfg(feature = "state-transitions")]
16use crate::state_transition::batch_transition::{
17    batched_transition::document_transition_action_type::DocumentTransitionActionType,
18    BatchTransition,
19};
20use crate::tokens::token_payment_info::TokenPaymentInfo;
21use crate::util::entropy_generator::EntropyGenerator;
22pub use v0::SpecializedDocumentFactoryV0;
23
24/// # Document Factory
25///
26/// This module is responsible for creating instances of documents for a specific contract.
27///
28/// ## Versioning
29///
30/// The factory is versioned because the process of creating documents
31/// can change over time. Changes may be due to modifications in
32/// requirements, alterations in the document structure, or evolution in the
33/// dependencies of the document. Versioning allows for these changes to be
34/// tracked and managed effectively, providing flexibility to handle different
35/// versions of documents as needed.
36#[derive(From)]
37pub enum SpecializedDocumentFactory {
38    /// The version 0 implementation of the data contract factory.
39    V0(SpecializedDocumentFactoryV0),
40}
41
42impl SpecializedDocumentFactory {
43    /// Create a new document factory knowing versions
44    pub fn new(protocol_version: u32, data_contract: DataContract) -> Result<Self, ProtocolError> {
45        let platform_version = PlatformVersion::get(protocol_version)?;
46        match platform_version
47            .dpp
48            .factory_versions
49            .document_factory_structure_version
50        {
51            0 => Ok(SpecializedDocumentFactoryV0::new(protocol_version, data_contract).into()),
52            version => Err(ProtocolError::UnknownVersionMismatch {
53                method: "DocumentFactory::new".to_string(),
54                known_versions: vec![0],
55                received: version,
56            }),
57        }
58    }
59
60    pub fn new_with_entropy_generator(
61        protocol_version: u32,
62        data_contract: DataContract,
63        entropy_generator: Box<dyn EntropyGenerator>,
64    ) -> Result<Self, ProtocolError> {
65        let platform_version = PlatformVersion::get(protocol_version)?;
66        match platform_version
67            .dpp
68            .factory_versions
69            .document_factory_structure_version
70        {
71            0 => Ok(SpecializedDocumentFactoryV0::new_with_entropy_generator(
72                protocol_version,
73                data_contract,
74                entropy_generator,
75            )
76            .into()),
77            version => Err(ProtocolError::UnknownVersionMismatch {
78                method: "DocumentFactory::new_with_entropy_generator".to_string(),
79                known_versions: vec![0],
80                received: version,
81            }),
82        }
83    }
84
85    pub fn data_contract(&self) -> &DataContract {
86        match self {
87            SpecializedDocumentFactory::V0(v0) => &v0.data_contract,
88        }
89    }
90
91    pub fn create_document(
92        &self,
93        owner_id: Identifier,
94        document_type_name: String,
95        data: Value,
96    ) -> Result<Document, ProtocolError> {
97        match self {
98            SpecializedDocumentFactory::V0(v0) => {
99                v0.create_document_without_time_based_properties(owner_id, document_type_name, data)
100            }
101        }
102    }
103
104    #[cfg(feature = "extended-document")]
105    pub fn create_extended_document(
106        &self,
107        owner_id: Identifier,
108        document_type_name: String,
109        data: Value,
110    ) -> Result<ExtendedDocument, ProtocolError> {
111        match self {
112            SpecializedDocumentFactory::V0(v0) => {
113                v0.create_extended_document(owner_id, document_type_name, data)
114            }
115        }
116    }
117
118    #[cfg(feature = "state-transitions")]
119    pub fn create_state_transition<'a>(
120        &self,
121        documents_iter: impl IntoIterator<
122            Item = (
123                DocumentTransitionActionType,
124                Vec<(
125                    Document,
126                    DocumentTypeRef<'a>,
127                    Bytes32,
128                    Option<TokenPaymentInfo>,
129                )>,
130            ),
131        >,
132        nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, //IdentityID/ContractID -> nonce
133    ) -> Result<BatchTransition, ProtocolError> {
134        match self {
135            SpecializedDocumentFactory::V0(v0) => {
136                v0.create_state_transition(documents_iter, nonce_counter)
137            }
138        }
139    }
140
141    #[cfg(feature = "extended-document")]
142    pub fn create_extended_from_document_buffer(
143        &self,
144        buffer: &[u8],
145        document_type_name: &str,
146        platform_version: &PlatformVersion,
147    ) -> Result<ExtendedDocument, ProtocolError> {
148        match self {
149            SpecializedDocumentFactory::V0(v0) => v0.create_extended_from_document_buffer(
150                buffer,
151                document_type_name,
152                platform_version,
153            ),
154        }
155    }
156}