1use crate::drive::votes::paths::vote_contested_resource_identity_votes_tree_path_for_identity_vec;
2#[cfg(feature = "server")]
3use crate::drive::votes::storage_form::contested_document_resource_reference_storage_form::ContestedDocumentResourceVoteReferenceStorageForm;
4#[cfg(feature = "server")]
5use crate::drive::votes::storage_form::contested_document_resource_storage_form::ContestedDocumentResourceVoteStorageForm;
6#[cfg(feature = "server")]
7use crate::drive::votes::tree_path_storage_form::TreePathStorageForm;
8#[cfg(feature = "server")]
9use crate::drive::Drive;
10#[cfg(feature = "server")]
11use crate::error::drive::DriveError;
12use crate::error::Error;
13#[cfg(feature = "server")]
14use crate::fees::op::LowLevelDriveOperation;
15#[cfg(feature = "server")]
16use crate::query::GroveError;
17use crate::query::Query;
18#[cfg(feature = "server")]
19use dpp::bincode;
20#[cfg(feature = "server")]
21use dpp::block::block_info::BlockInfo;
22use dpp::identifier::Identifier;
23#[cfg(feature = "server")]
24use grovedb::query_result_type::{QueryResultElements, QueryResultType};
25#[cfg(feature = "server")]
26use grovedb::TransactionArg;
27use grovedb::{PathQuery, SizedQuery};
28#[cfg(feature = "server")]
29use platform_version::version::PlatformVersion;
30#[cfg(feature = "server")]
31use std::collections::BTreeMap;
32
33#[derive(Debug, PartialEq, Clone)]
35pub struct ContestedResourceVotesGivenByIdentityQuery {
36 pub identity_id: Identifier,
38 pub offset: Option<u16>,
40 pub limit: Option<u16>,
42 pub start_at: Option<([u8; 32], bool)>,
44 pub order_ascending: bool,
46}
47
48impl ContestedResourceVotesGivenByIdentityQuery {
49 #[cfg(feature = "server")]
50 pub fn execute_with_proof(
52 self,
53 drive: &Drive,
54 block_info: Option<BlockInfo>,
55 transaction: TransactionArg,
56 platform_version: &PlatformVersion,
57 ) -> Result<(Vec<u8>, u64), Error> {
58 let mut drive_operations = vec![];
59 let items = self.execute_with_proof_internal(
60 drive,
61 transaction,
62 &mut drive_operations,
63 platform_version,
64 )?;
65 let cost = if let Some(block_info) = block_info {
66 let fee_result = Drive::calculate_fee(
67 None,
68 Some(drive_operations),
69 &block_info.epoch,
70 drive.config.epochs_per_era,
71 platform_version,
72 None,
73 )?;
74 fee_result.processing_fee
75 } else {
76 0
77 };
78 Ok((items, cost))
79 }
80
81 #[cfg(feature = "server")]
82 pub(crate) fn execute_with_proof_internal(
84 self,
85 drive: &Drive,
86 transaction: TransactionArg,
87 drive_operations: &mut Vec<LowLevelDriveOperation>,
88 platform_version: &PlatformVersion,
89 ) -> Result<Vec<u8>, Error> {
90 let path_query = self.construct_path_query()?;
91 drive.grove_get_proved_path_query(
92 &path_query,
93 transaction,
94 drive_operations,
95 &platform_version.drive,
96 )
97 }
98
99 #[cfg(feature = "server")]
100 pub fn execute_no_proof_with_cost(
102 &self,
103 drive: &Drive,
104 block_info: Option<BlockInfo>,
105 transaction: TransactionArg,
106 platform_version: &PlatformVersion,
107 ) -> Result<
108 (
109 BTreeMap<Identifier, ContestedDocumentResourceVoteStorageForm>,
110 u64,
111 ),
112 Error,
113 > {
114 let mut drive_operations = vec![];
115 let result =
116 self.execute_no_proof(drive, transaction, &mut drive_operations, platform_version)?;
117 let cost = if let Some(block_info) = block_info {
118 let fee_result = Drive::calculate_fee(
119 None,
120 Some(drive_operations),
121 &block_info.epoch,
122 drive.config.epochs_per_era,
123 platform_version,
124 None,
125 )?;
126 fee_result.processing_fee
127 } else {
128 0
129 };
130 Ok((result, cost))
131 }
132
133 #[cfg(feature = "server")]
134 pub fn execute_no_proof(
136 &self,
137 drive: &Drive,
138 transaction: TransactionArg,
139 drive_operations: &mut Vec<LowLevelDriveOperation>,
140 platform_version: &PlatformVersion,
141 ) -> Result<BTreeMap<Identifier, ContestedDocumentResourceVoteStorageForm>, Error> {
142 let path_query = self.construct_path_query()?;
143 let query_result = drive.grove_get_raw_path_query(
144 &path_query,
145 transaction,
146 QueryResultType::QueryPathKeyElementTrioResultType,
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(BTreeMap::new())
160 }
161 Err(e) => Err(e),
162 Ok((query_result_elements, _)) => {
163 let voters =
164 query_result_elements
165 .to_path_key_elements()
166 .into_iter()
167 .map(|(path, key, element)| {
168 let serialized_reference = element.into_item_bytes()?;
169 let bincode_config = bincode::config::standard()
170 .with_big_endian()
171 .with_no_limit();
172 let reference: ContestedDocumentResourceVoteReferenceStorageForm =
173 bincode::decode_from_slice(&serialized_reference, bincode_config)
174 .map_err(|e| {
175 Error::Drive(DriveError::CorruptedSerialization(format!(
176 "serialization of reference {} is corrupted: {}",
177 hex::encode(serialized_reference),
178 e
179 )))
180 })?
181 .0;
182 let absolute_path = reference
183 .reference_path_type
184 .absolute_path(path.as_slice(), Some(key.as_slice()))?;
185 let vote_id = Identifier::from_vec(key)?;
186 Ok((
187 vote_id,
188 ContestedDocumentResourceVoteStorageForm::try_from_tree_path(
189 absolute_path,
190 )?,
191 ))
192 })
193 .collect::<Result<
194 BTreeMap<Identifier, ContestedDocumentResourceVoteStorageForm>,
195 Error,
196 >>()?;
197
198 Ok(voters)
199 }
200 }
201 }
202
203 #[cfg(feature = "server")]
204 #[allow(unused)]
205 pub(crate) fn execute_no_proof_internal(
207 &self,
208 drive: &Drive,
209 result_type: QueryResultType,
210 transaction: TransactionArg,
211 drive_operations: &mut Vec<LowLevelDriveOperation>,
212 platform_version: &PlatformVersion,
213 ) -> Result<(QueryResultElements, u16), Error> {
214 let path_query = self.construct_path_query()?;
215 let query_result = drive.grove_get_path_query(
216 &path_query,
217 transaction,
218 result_type,
219 drive_operations,
220 &platform_version.drive,
221 );
222 match query_result {
223 Err(Error::GroveDB(e))
224 if matches!(
225 e.as_ref(),
226 GroveError::PathKeyNotFound(_)
227 | GroveError::PathNotFound(_)
228 | GroveError::PathParentLayerNotFound(_)
229 ) =>
230 {
231 Ok((QueryResultElements::new(), 0))
232 }
233 _ => {
234 let (data, skipped) = query_result?;
235 {
236 Ok((data, skipped))
237 }
238 }
239 }
240 }
241 pub fn construct_path_query(&self) -> Result<PathQuery, Error> {
243 let path = vote_contested_resource_identity_votes_tree_path_for_identity_vec(
244 self.identity_id.as_bytes(),
245 );
246
247 let mut query = Query::new_with_direction(self.order_ascending);
248
249 match &self.start_at {
251 None => {
252 query.insert_all();
253 }
254 Some((starts_at_key_bytes, start_at_included)) => {
255 let starts_at_key = starts_at_key_bytes.to_vec();
256 match self.order_ascending {
257 true => match start_at_included {
258 true => query.insert_range_from(starts_at_key..),
259 false => query.insert_range_after(starts_at_key..),
260 },
261 false => match start_at_included {
262 true => query.insert_range_to_inclusive(..=starts_at_key),
263 false => query.insert_range_to(..starts_at_key),
264 },
265 }
266 }
267 }
268
269 Ok(PathQuery {
270 path,
271 query: SizedQuery {
272 query,
273 limit: self.limit,
274 offset: self.offset,
275 },
276 })
277 }
278}