1#[cfg(feature = "verify")]
2use super::ContractLookupFn;
3use crate::drive::votes::paths::VotePollPaths;
4#[cfg(any(feature = "server", feature = "verify"))]
5use crate::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::resolve::ContestedDocumentResourceVotePollResolver;
6use crate::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed;
7#[cfg(feature = "server")]
8use crate::drive::Drive;
9use crate::error::Error;
10#[cfg(feature = "server")]
11use crate::fees::op::LowLevelDriveOperation;
12#[cfg(feature = "server")]
13use crate::query::GroveError;
14use crate::query::Query;
15use bincode::{Decode, Encode};
16#[cfg(feature = "server")]
17use dpp::block::block_info::BlockInfo;
18use dpp::identifier::Identifier;
19#[cfg(feature = "server")]
20use dpp::platform_value;
21use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice::TowardsIdentity;
22use dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll;
23#[cfg(feature = "server")]
24use grovedb::query_result_type::{QueryResultElements, QueryResultType};
25#[cfg(feature = "server")]
26use grovedb::TransactionArg;
27use grovedb::{PathQuery, SizedQuery};
28use platform_version::version::PlatformVersion;
29
30#[derive(Debug, PartialEq, Clone, Encode, Decode)]
32pub struct ContestedDocumentVotePollVotesDriveQuery {
33 pub vote_poll: ContestedDocumentResourceVotePoll,
35 pub contestant_id: Identifier,
37 pub offset: Option<u16>,
39 pub limit: Option<u16>,
41 pub start_at: Option<([u8; 32], bool)>,
43 pub order_ascending: bool,
45}
46
47impl ContestedDocumentVotePollVotesDriveQuery {
48 #[cfg(feature = "server")]
49 pub fn resolve(
70 &self,
71 drive: &Drive,
72 transaction: TransactionArg,
73 platform_version: &PlatformVersion,
74 ) -> Result<ResolvedContestedDocumentVotePollVotesDriveQuery<'_>, Error> {
75 let ContestedDocumentVotePollVotesDriveQuery {
76 vote_poll,
77 contestant_id,
78 offset,
79 limit,
80 start_at,
81 order_ascending,
82 } = self;
83 Ok(ResolvedContestedDocumentVotePollVotesDriveQuery {
84 vote_poll: vote_poll.resolve_allow_borrowed(drive, transaction, platform_version)?,
85 contestant_id: *contestant_id,
86 offset: *offset,
87 limit: *limit,
88 start_at: *start_at,
89 order_ascending: *order_ascending,
90 })
91 }
92
93 #[cfg(feature = "verify")]
97 pub fn resolve_with_known_contracts_provider<'a>(
98 &self,
99 known_contracts_provider: &ContractLookupFn,
100 ) -> Result<ResolvedContestedDocumentVotePollVotesDriveQuery<'a>, Error> {
101 let ContestedDocumentVotePollVotesDriveQuery {
102 vote_poll,
103 contestant_id,
104 offset,
105 limit,
106 start_at,
107 order_ascending,
108 } = self;
109 Ok(ResolvedContestedDocumentVotePollVotesDriveQuery {
110 vote_poll: vote_poll.resolve_with_known_contracts_provider(known_contracts_provider)?,
111 contestant_id: *contestant_id,
112 offset: *offset,
113 limit: *limit,
114 start_at: *start_at,
115 order_ascending: *order_ascending,
116 })
117 }
118
119 #[cfg(feature = "server")]
120 pub fn execute_with_proof(
122 self,
123 drive: &Drive,
124 block_info: Option<BlockInfo>,
125 transaction: TransactionArg,
126 platform_version: &PlatformVersion,
127 ) -> Result<(Vec<u8>, u64), Error> {
128 let mut drive_operations = vec![];
129 let items = self.execute_with_proof_internal(
130 drive,
131 transaction,
132 &mut drive_operations,
133 platform_version,
134 )?;
135 let cost = if let Some(block_info) = block_info {
136 let fee_result = Drive::calculate_fee(
137 None,
138 Some(drive_operations),
139 &block_info.epoch,
140 drive.config.epochs_per_era,
141 platform_version,
142 None,
143 )?;
144 fee_result.processing_fee
145 } else {
146 0
147 };
148 Ok((items, cost))
149 }
150
151 #[cfg(feature = "server")]
152 pub(crate) fn execute_with_proof_internal(
154 self,
155 drive: &Drive,
156 transaction: TransactionArg,
157 drive_operations: &mut Vec<LowLevelDriveOperation>,
158 platform_version: &PlatformVersion,
159 ) -> Result<Vec<u8>, Error> {
160 let resolved = self.resolve(drive, transaction, platform_version)?;
161 let path_query = resolved.construct_path_query(platform_version)?;
162 drive.grove_get_proved_path_query(
163 &path_query,
164 transaction,
165 drive_operations,
166 &platform_version.drive,
167 )
168 }
169
170 #[cfg(feature = "server")]
171 pub fn execute_no_proof_with_cost(
173 &self,
174 drive: &Drive,
175 block_info: Option<BlockInfo>,
176 transaction: TransactionArg,
177 platform_version: &PlatformVersion,
178 ) -> Result<(Vec<Identifier>, u64), Error> {
179 let mut drive_operations = vec![];
180 let result =
181 self.execute_no_proof(drive, transaction, &mut drive_operations, platform_version)?;
182 let cost = if let Some(block_info) = block_info {
183 let fee_result = Drive::calculate_fee(
184 None,
185 Some(drive_operations),
186 &block_info.epoch,
187 drive.config.epochs_per_era,
188 platform_version,
189 None,
190 )?;
191 fee_result.processing_fee
192 } else {
193 0
194 };
195 Ok((result, cost))
196 }
197
198 #[cfg(feature = "server")]
199 pub fn execute_no_proof(
201 &self,
202 drive: &Drive,
203 transaction: TransactionArg,
204 drive_operations: &mut Vec<LowLevelDriveOperation>,
205 platform_version: &PlatformVersion,
206 ) -> Result<Vec<Identifier>, Error> {
207 let resolved = self.resolve(drive, transaction, platform_version)?;
208 let path_query = resolved.construct_path_query(platform_version)?;
209 let query_result = drive.grove_get_path_query(
210 &path_query,
211 transaction,
212 QueryResultType::QueryPathKeyElementTrioResultType,
213 drive_operations,
214 &platform_version.drive,
215 );
216 match query_result {
217 Err(Error::GroveDB(e))
218 if matches!(
219 e.as_ref(),
220 GroveError::PathKeyNotFound(_)
221 | GroveError::PathNotFound(_)
222 | GroveError::PathParentLayerNotFound(_)
223 ) =>
224 {
225 Ok(vec![])
226 }
227 Err(e) => Err(e),
228 Ok((query_result_elements, _skipped)) => {
229 let voters = query_result_elements
230 .to_keys()
231 .into_iter()
232 .map(Identifier::try_from)
233 .collect::<Result<Vec<Identifier>, platform_value::Error>>()?;
234
235 Ok(voters)
236 }
237 }
238 }
239
240 #[cfg(feature = "server")]
241 #[allow(unused)]
242 pub(crate) fn execute_no_proof_internal(
244 &self,
245 drive: &Drive,
246 result_type: QueryResultType,
247 transaction: TransactionArg,
248 drive_operations: &mut Vec<LowLevelDriveOperation>,
249 platform_version: &PlatformVersion,
250 ) -> Result<(QueryResultElements, u16), Error> {
251 let resolved = self.resolve(drive, transaction, platform_version)?;
252 let path_query = resolved.construct_path_query(platform_version)?;
253 let query_result = drive.grove_get_path_query(
254 &path_query,
255 transaction,
256 result_type,
257 drive_operations,
258 &platform_version.drive,
259 );
260 match query_result {
261 Err(Error::GroveDB(e))
262 if matches!(
263 e.as_ref(),
264 GroveError::PathKeyNotFound(_)
265 | GroveError::PathNotFound(_)
266 | GroveError::PathParentLayerNotFound(_)
267 ) =>
268 {
269 Ok((QueryResultElements::new(), 0))
270 }
271 _ => {
272 let (data, skipped) = query_result?;
273 {
274 Ok((data, skipped))
275 }
276 }
277 }
278 }
279}
280#[derive(Debug, PartialEq, Clone)]
282pub struct ResolvedContestedDocumentVotePollVotesDriveQuery<'a> {
283 pub vote_poll: ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed<'a>,
285 pub contestant_id: Identifier,
287 pub offset: Option<u16>,
289 pub limit: Option<u16>,
291 pub start_at: Option<([u8; 32], bool)>,
293 pub order_ascending: bool,
295}
296
297impl ResolvedContestedDocumentVotePollVotesDriveQuery<'_> {
298 pub fn construct_path_query(
300 &self,
301 platform_version: &PlatformVersion,
302 ) -> Result<PathQuery, Error> {
303 let path = self
304 .vote_poll
305 .contender_voting_path(&TowardsIdentity(self.contestant_id), platform_version)?;
306
307 let mut query = Query::new_with_direction(self.order_ascending);
308
309 match &self.start_at {
311 None => {
312 query.insert_all();
313 }
314 Some((starts_at_key_bytes, start_at_included)) => {
315 let starts_at_key = starts_at_key_bytes.to_vec();
316 match self.order_ascending {
317 true => match start_at_included {
318 true => query.insert_range_from(starts_at_key..),
319 false => query.insert_range_after(starts_at_key..),
320 },
321 false => match start_at_included {
322 true => query.insert_range_to_inclusive(..=starts_at_key),
323 false => query.insert_range_to(..starts_at_key),
324 },
325 }
326 }
327 }
328
329 Ok(PathQuery {
330 path,
331 query: SizedQuery {
332 query,
333 limit: self.limit,
334 offset: self.offset,
335 },
336 })
337 }
338}