drive/query/
drive_contested_document_query.rs1use 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#[derive(Clone, Debug, PartialEq, Default)]
26pub struct PrimaryContestedInternalClauses {
27 pub primary_key_in_clause: Option<Vec<Identifier>>,
29 pub primary_key_equal_clause: Option<Identifier>,
31}
32
33impl PrimaryContestedInternalClauses {
34 #[cfg(any(feature = "server", feature = "verify"))]
35 pub fn verify(&self) -> bool {
37 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#[derive(Debug, PartialEq, Clone)]
47pub struct DriveContestedDocumentQuery<'a> {
48 pub contract: &'a DataContract,
50 pub document_type: DocumentTypeRef<'a>,
52 pub internal_clauses: PrimaryContestedInternalClauses,
54}
55
56impl DriveContestedDocumentQuery<'_> {
57 #[cfg(any(feature = "server", feature = "verify"))]
58 pub fn construct_path_query(
60 &self,
61 _platform_version: &PlatformVersion,
62 ) -> Result<PathQuery, Error> {
63 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 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 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 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}