drive/util/batch/drive_op_batch/
contract.rs

1use crate::drive::Drive;
2use crate::error::Error;
3use crate::fees::op::LowLevelDriveOperation;
4use crate::util::batch::drive_op_batch::DriveLowLevelOperationConverter;
5use crate::util::storage_flags::StorageFlags;
6use dpp::block::block_info::BlockInfo;
7use dpp::data_contract::DataContract;
8
9use crate::error::drive::DriveError;
10use crate::util::batch::drive_op_batch::finalize_task::{
11    DriveOperationFinalizationTasks, DriveOperationFinalizeTask,
12};
13use dpp::data_contract::accessors::v0::DataContractV0Getters;
14
15use dpp::version::PlatformVersion;
16use grovedb::batch::KeyInfoPath;
17use grovedb::{EstimatedLayerInformation, TransactionArg};
18use std::borrow::{Borrow, Cow};
19use std::collections::HashMap;
20
21/// Operations on DataContracts
22#[derive(Clone, Debug)]
23pub enum DataContractOperationType<'a> {
24    /// Applies a contract and returns the fee for applying.
25    /// If the contract already exists, an update is applied, otherwise an insert.
26    ApplyContractWithSerialization {
27        /// The contract
28        contract: Cow<'a, DataContract>,
29        /// The serialized contract
30        serialized_contract: Vec<u8>,
31        /// Storage flags for the contract
32        storage_flags: Option<Cow<'a, StorageFlags>>,
33    },
34    // TODO: split into create and update
35    /// Applies a contract without serialization.
36    ApplyContract {
37        // this is Cow because we want to allow the contract to be owned or not
38        // ownership is interesting because you can easily create the contract
39        // in sub functions
40        // borrowing is interesting because you can create the contract and then
41        // use it as borrowed for document insertions
42        /// The contract
43        contract: Cow<'a, DataContract>,
44        /// Storage flags for the contract
45        storage_flags: Option<Cow<'a, StorageFlags>>,
46    },
47}
48
49impl DriveLowLevelOperationConverter for DataContractOperationType<'_> {
50    fn into_low_level_drive_operations(
51        self,
52        drive: &Drive,
53        estimated_costs_only_with_layer_info: &mut Option<
54            HashMap<KeyInfoPath, EstimatedLayerInformation>,
55        >,
56        block_info: &BlockInfo,
57        transaction: TransactionArg,
58        platform_version: &PlatformVersion,
59    ) -> Result<Vec<LowLevelDriveOperation>, Error> {
60        match self {
61            DataContractOperationType::ApplyContractWithSerialization {
62                contract,
63                serialized_contract: contract_serialization,
64                storage_flags,
65            } => drive.apply_contract_with_serialization_operations(
66                contract.borrow(),
67                contract_serialization,
68                block_info,
69                estimated_costs_only_with_layer_info,
70                storage_flags,
71                transaction,
72                platform_version,
73            ),
74            DataContractOperationType::ApplyContract {
75                contract,
76                storage_flags,
77            } => drive.apply_contract_operations(
78                contract.borrow(),
79                block_info,
80                estimated_costs_only_with_layer_info,
81                storage_flags,
82                transaction,
83                platform_version,
84            ),
85        }
86    }
87}
88
89impl DriveOperationFinalizationTasks for DataContractOperationType<'_> {
90    fn finalization_tasks(
91        &self,
92        platform_version: &PlatformVersion,
93    ) -> Result<Option<Vec<DriveOperationFinalizeTask>>, Error> {
94        match platform_version
95            .drive
96            .methods
97            .state_transitions
98            .operations
99            .contracts
100            .finalization_tasks
101        {
102            0 => self.finalization_tasks_v0(),
103            version => Err(Error::Drive(DriveError::UnknownVersionMismatch {
104                method: "DataContractOperationType.finalization_tasks".to_string(),
105                known_versions: vec![0],
106                received: version,
107            })),
108        }
109    }
110}
111
112impl DataContractOperationType<'_> {
113    fn finalization_tasks_v0(&self) -> Result<Option<Vec<DriveOperationFinalizeTask>>, Error> {
114        let tasks = match self {
115            Self::ApplyContractWithSerialization { contract, .. }
116            | Self::ApplyContract { contract, .. } => {
117                vec![DriveOperationFinalizeTask::RemoveDataContractFromCache {
118                    contract_id: contract.id(),
119                }]
120            }
121        };
122
123        Ok(Some(tasks))
124    }
125}