drive/query/
drive_contested_document_query.rs

1use crate::drive::contract::paths::DataContractPaths;
2#[cfg(feature = "server")]
3use crate::drive::Drive;
4use crate::error::Error;
5#[cfg(feature = "server")]
6use crate::fees::op::LowLevelDriveOperation;
7#[cfg(feature = "server")]
8use crate::query::GroveError;
9use crate::query::Query;
10#[cfg(feature = "server")]
11use dpp::block::block_info::BlockInfo;
12use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
13use dpp::data_contract::document_type::DocumentTypeRef;
14use dpp::data_contract::DataContract;
15use dpp::prelude::Identifier;
16#[cfg(feature = "server")]
17use grovedb::TransactionArg;
18#[cfg(any(feature = "server", feature = "verify"))]
19use grovedb::{PathQuery, SizedQuery};
20use platform_version::version::PlatformVersion;
21use std::ops::BitXor;
22
23#[cfg(any(feature = "server", feature = "verify"))]
24/// Internal clauses struct
25#[derive(Clone, Debug, PartialEq, Default)]
26pub struct PrimaryContestedInternalClauses {
27    /// Primary key in clause
28    pub primary_key_in_clause: Option<Vec<Identifier>>,
29    /// Primary key equal clause
30    pub primary_key_equal_clause: Option<Identifier>,
31}
32
33impl PrimaryContestedInternalClauses {
34    #[cfg(any(feature = "server", feature = "verify"))]
35    /// Returns true if the clause is a valid format.
36    pub fn verify(&self) -> bool {
37        // There can only be 1 primary key clause
38        self.primary_key_in_clause
39            .is_some()
40            .bitxor(self.primary_key_equal_clause.is_some())
41    }
42}
43
44#[cfg(any(feature = "server", feature = "verify"))]
45/// Drive query struct
46#[derive(Debug, PartialEq, Clone)]
47pub struct DriveContestedDocumentQuery<'a> {
48    ///DataContract
49    pub contract: &'a DataContract,
50    /// Document type
51    pub document_type: DocumentTypeRef<'a>,
52    /// Internal clauses
53    pub internal_clauses: PrimaryContestedInternalClauses,
54}
55
56impl DriveContestedDocumentQuery<'_> {
57    #[cfg(any(feature = "server", feature = "verify"))]
58    /// Returns a path query given a document type path and starting document.
59    pub fn construct_path_query(
60        &self,
61        _platform_version: &PlatformVersion,
62    ) -> Result<PathQuery, Error> {
63        // First we should get the overall document_type_path
64        let mut path = self
65            .contract
66            .contested_document_type_path(self.document_type.name().as_str())
67            .into_iter()
68            .map(|a| a.to_vec())
69            .collect::<Vec<Vec<u8>>>();
70
71        // Add primary key ($id) subtree
72        path.push(vec![0]);
73
74        if let Some(primary_key_equal_clause) = &self.internal_clauses.primary_key_equal_clause {
75            let mut query = Query::new();
76            query.insert_key(primary_key_equal_clause.to_vec());
77
78            Ok(PathQuery::new(path, SizedQuery::new(query, Some(1), None)))
79        } else {
80            let mut query = Query::new();
81
82            if let Some(primary_key_in_clause) = &self.internal_clauses.primary_key_in_clause {
83                query.insert_keys(
84                    primary_key_in_clause
85                        .iter()
86                        .map(|identifier| identifier.to_vec())
87                        .collect(),
88                );
89
90                Ok(PathQuery::new(
91                    path,
92                    SizedQuery::new(query, Some(primary_key_in_clause.len() as u16), None),
93                ))
94            } else {
95                query.insert_all();
96
97                Ok(PathQuery::new(path, SizedQuery::new(query, None, None)))
98            }
99        }
100    }
101
102    #[cfg(feature = "server")]
103    /// Executes a query with no proof and returns the items, skipped items, and fee.
104    pub fn execute_raw_results_no_proof(
105        &self,
106        drive: &Drive,
107        block_info: Option<BlockInfo>,
108        transaction: TransactionArg,
109        platform_version: &PlatformVersion,
110    ) -> Result<(Vec<Vec<u8>>, u64), Error> {
111        let mut drive_operations = vec![];
112        let (items, _skipped) = self.execute_raw_results_no_proof_internal(
113            drive,
114            transaction,
115            &mut drive_operations,
116            platform_version,
117        )?;
118        let cost = if let Some(block_info) = block_info {
119            let fee_result = Drive::calculate_fee(
120                None,
121                Some(drive_operations),
122                &block_info.epoch,
123                drive.config.epochs_per_era,
124                platform_version,
125                None,
126            )?;
127            fee_result.processing_fee
128        } else {
129            0
130        };
131        Ok((items, cost))
132    }
133
134    #[cfg(feature = "server")]
135    /// Executes an internal query with no proof and returns the values and skipped items.
136    pub(crate) fn execute_raw_results_no_proof_internal(
137        &self,
138        drive: &Drive,
139        transaction: TransactionArg,
140        drive_operations: &mut Vec<LowLevelDriveOperation>,
141        platform_version: &PlatformVersion,
142    ) -> Result<(Vec<Vec<u8>>, u16), Error> {
143        let path_query = self.construct_path_query(platform_version)?;
144        let query_result = drive.grove_get_path_query_serialized_results(
145            &path_query,
146            transaction,
147            drive_operations,
148            &platform_version.drive,
149        );
150        match query_result {
151            Err(Error::GroveDB(e))
152                if matches!(
153                    e.as_ref(),
154                    GroveError::PathKeyNotFound(_)
155                        | GroveError::PathNotFound(_)
156                        | GroveError::PathParentLayerNotFound(_)
157                ) =>
158            {
159                Ok((Vec::new(), 0))
160            }
161            _ => {
162                let (data, skipped) = query_result?;
163                {
164                    Ok((data, skipped))
165                }
166            }
167        }
168    }
169}