1mod address_funds;
2mod data_contract_based_queries;
3mod document_query;
4mod group_queries;
5mod identity_based_queries;
6mod prefunded_specialized_balances;
7mod proofs;
8mod response_metadata;
9mod service;
10mod shielded;
11mod system;
12mod token_queries;
13mod validator_queries;
14mod voting;
15
16use crate::error::query::QueryError;
17
18use dpp::validation::ValidationResult;
19
20pub use service::QueryService;
21
22pub type QueryValidationResult<TData> = ValidationResult<TData, QueryError>;
24
25#[cfg(test)]
26pub(crate) mod tests {
27 use crate::error::query::QueryError;
28 use crate::platform_types::platform::Platform;
29 use crate::platform_types::platform_state::PlatformState;
30 use crate::platform_types::platform_state::PlatformStateV0Methods;
31 use crate::query::QueryValidationResult;
32 use crate::rpc::core::MockCoreRPCLike;
33 use crate::test::helpers::setup::{TempPlatform, TestPlatformBuilder};
34 use dpp::block::block_info::BlockInfo;
35 use dpp::data_contract::DataContract;
36
37 use crate::config::PlatformConfig;
38 use dpp::dashcore::Network;
39 use dpp::data_contract::document_type::DocumentTypeRef;
40 use dpp::document::Document;
41 use dpp::prelude::{CoreBlockHeight, TimestampMillis};
42 use drive::util::batch::DriveOperation::{DataContractOperation, DocumentOperation};
43 use drive::util::batch::{DataContractOperationType, DocumentOperationType};
44 use drive::util::object_size_info::{
45 DataContractInfo, DocumentInfo, DocumentTypeInfo, OwnedDocumentInfo,
46 };
47 use drive::util::storage_flags::StorageFlags;
48 use platform_version::version::{PlatformVersion, ProtocolVersion};
49 use std::borrow::Cow;
50 use std::sync::Arc;
51
52 pub fn setup_platform<'a>(
53 with_genesis_state: Option<(TimestampMillis, CoreBlockHeight)>,
54 network: Network,
55 initial_protocol_version: Option<ProtocolVersion>,
56 ) -> (
57 TempPlatform<MockCoreRPCLike>,
58 Arc<PlatformState>,
59 &'a PlatformVersion,
60 ) {
61 let platform = if let Some((timestamp, activation_core_block_height)) = with_genesis_state {
62 let mut platform_builder = TestPlatformBuilder::new()
63 .with_config(PlatformConfig::default_for_network(network));
64
65 if let Some(initial_protocol_version) = initial_protocol_version {
66 platform_builder =
67 platform_builder.with_initial_protocol_version(initial_protocol_version);
68 }
69
70 platform_builder
71 .build_with_mock_rpc()
72 .set_genesis_state_with_activation_info(timestamp, activation_core_block_height)
73 } else {
74 let mut platform_builder = TestPlatformBuilder::new()
75 .with_config(PlatformConfig::default_for_network(network));
76
77 if let Some(initial_protocol_version) = initial_protocol_version {
78 platform_builder =
79 platform_builder.with_initial_protocol_version(initial_protocol_version);
80 }
81
82 platform_builder
83 .build_with_mock_rpc()
84 .set_initial_state_structure()
85 };
86
87 let platform_state = platform.platform.state.load_full();
90
91 let platform_version = platform_state.current_platform_version().unwrap();
92
93 (platform, platform_state, platform_version)
94 }
95
96 pub fn store_data_contract(
97 platform: &Platform<MockCoreRPCLike>,
98 data_contract: &DataContract,
99 platform_version: &PlatformVersion,
100 ) {
101 let operation = DataContractOperation(DataContractOperationType::ApplyContract {
102 contract: Cow::Owned(data_contract.to_owned()),
103 storage_flags: None,
104 });
105
106 let block_info = BlockInfo::genesis();
107
108 platform
109 .drive
110 .apply_drive_operations(
111 vec![operation],
112 true,
113 &block_info,
114 None,
115 platform_version,
116 None,
117 )
118 .expect("expected to apply drive operations");
119 }
120
121 pub fn store_document(
122 platform: &Platform<MockCoreRPCLike>,
123 data_contract: &DataContract,
124 document_type: DocumentTypeRef,
125 document: &Document,
126 platform_version: &PlatformVersion,
127 ) {
128 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
129
130 let operation = DocumentOperation(DocumentOperationType::AddDocument {
131 owned_document_info: OwnedDocumentInfo {
132 document_info: DocumentInfo::DocumentRefInfo((document, storage_flags)),
133 owner_id: None,
134 },
135 contract_info: DataContractInfo::BorrowedDataContract(data_contract),
136 document_type_info: DocumentTypeInfo::DocumentTypeRef(document_type),
137 override_document: false,
138 });
139
140 let block_info = BlockInfo::genesis();
141
142 platform
143 .drive
144 .apply_drive_operations(
145 vec![operation],
146 true,
147 &block_info,
148 None,
149 platform_version,
150 None,
151 )
152 .expect("expected to apply drive operations");
153 }
154
155 pub fn assert_invalid_identifier<TData: Clone>(
156 validation_result: QueryValidationResult<TData>,
157 ) {
158 assert!(matches!(
159 validation_result.errors.as_slice(),
160 [QueryError::InvalidArgument(msg)] if msg.contains("id must be a valid identifier (32 bytes long)")
161 ));
162 }
163
164 #[allow(clippy::type_complexity)]
174 pub fn setup_platform_with_token_state<'a>() -> (
175 TempPlatform<MockCoreRPCLike>,
176 Arc<PlatformState>,
177 &'a PlatformVersion,
178 [u8; 32],
179 [[u8; 32]; 3],
180 [[u8; 32]; 3],
181 ) {
182 use dpp::data_contract::associated_token::token_configuration::v0::TokenConfigurationV0;
183 use dpp::data_contract::associated_token::token_configuration_convention::v0::TokenConfigurationConventionV0;
184 use dpp::data_contract::associated_token::token_distribution_rules::v0::TokenDistributionRulesV0;
185 use dpp::data_contract::associated_token::token_distribution_rules::TokenDistributionRules;
186 use dpp::data_contract::associated_token::token_keeps_history_rules::v0::TokenKeepsHistoryRulesV0;
187 use dpp::data_contract::associated_token::token_marketplace_rules::v0::TokenMarketplaceRulesV0;
188 use dpp::data_contract::associated_token::token_perpetual_distribution::distribution_function::DistributionFunction;
189 use dpp::data_contract::associated_token::token_perpetual_distribution::distribution_recipient::TokenDistributionRecipient;
190 use dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_type::RewardDistributionType;
191 use dpp::data_contract::associated_token::token_perpetual_distribution::v0::TokenPerpetualDistributionV0;
192 use dpp::data_contract::associated_token::token_perpetual_distribution::TokenPerpetualDistribution;
193 use dpp::data_contract::associated_token::token_pre_programmed_distribution::v0::TokenPreProgrammedDistributionV0;
194 use dpp::data_contract::associated_token::token_pre_programmed_distribution::TokenPreProgrammedDistribution;
195 use dpp::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers;
196 use dpp::data_contract::change_control_rules::v0::ChangeControlRulesV0;
197 use dpp::data_contract::config::DataContractConfig;
198 use dpp::data_contract::group::v0::GroupV0;
199 use dpp::data_contract::group::Group;
200 use dpp::data_contract::v1::DataContractV1;
201 use dpp::data_contract::{TokenConfiguration, INITIAL_DATA_CONTRACT_VERSION};
202 use dpp::identifier::Identifier;
203 use dpp::identity::accessors::IdentitySettersV0;
204 use dpp::identity::Identity;
205 use dpp::prelude::IdentityPublicKey;
206 use dpp::tokens::calculate_token_id;
207 use dpp::tokens::status::v0::TokenStatusV0;
208 use dpp::tokens::status::TokenStatus;
209 use dpp::tokens::token_pricing_schedule::TokenPricingSchedule;
210 use rand::rngs::StdRng;
211 use rand::SeedableRng;
212 use std::collections::BTreeMap;
213 use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
214
215 let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None);
216
217 let identity_id_1 = [1u8; 32];
218 let identity_id_2 = [2u8; 32];
219 let identity_id_3 = [3u8; 32];
220 let contract_id = [3u8; 32];
221
222 let token_id_0 = calculate_token_id(&contract_id, 0);
223 let token_id_1 = calculate_token_id(&contract_id, 1);
224 let token_id_2 = calculate_token_id(&contract_id, 2);
225
226 let credits_per_identity: u64 = 10_000_000_000_000;
228 let total_credits = credits_per_identity * 3;
229 platform
230 .platform
231 .drive
232 .add_to_system_credits(total_credits, None, version)
233 .expect("expected to add system credits");
234
235 let mut rng = StdRng::seed_from_u64(0u64);
236 let non_unique_key = IdentityPublicKey::random_voting_key_with_rng(11, &mut rng, version)
237 .expect("expected to create voting key");
238
239 for id_bytes in [identity_id_1, identity_id_2, identity_id_3] {
240 let id = Identifier::new(id_bytes);
241 let mut identity =
242 Identity::create_basic_identity(id, version).expect("expected to create identity");
243 identity.set_balance(credits_per_identity);
244
245 let seed = id_bytes[0];
246 let mut rng = StdRng::seed_from_u64(seed as u64);
247 let mut keys =
248 IdentityPublicKey::main_keys_with_random_authentication_keys_with_private_keys_with_rng(
249 3, &mut rng, version,
250 )
251 .expect("expected to create keys");
252
253 let transfer_key =
254 IdentityPublicKey::random_masternode_transfer_key_with_rng(3, &mut rng, version)
255 .expect("expected to create transfer key");
256 keys.push(transfer_key);
257 keys.push(non_unique_key.clone());
258
259 identity.set_public_keys(keys.into_iter().map(|(key, _)| (key.id(), key)).collect());
260
261 platform
262 .platform
263 .drive
264 .add_new_identity(identity, false, &BlockInfo::genesis(), true, None, version)
265 .expect("expected to add identity");
266 }
267
268 let groups = [
270 (
271 0,
272 Group::V0(GroupV0 {
273 members: [
274 (Identifier::new(identity_id_1), 1),
275 (Identifier::new(identity_id_2), 1),
276 ]
277 .into(),
278 required_power: 1,
279 }),
280 ),
281 (
282 1,
283 Group::V0(GroupV0 {
284 members: [
285 (Identifier::new(identity_id_1), 1),
286 (Identifier::new(identity_id_2), 1),
287 (Identifier::new(identity_id_3), 1),
288 ]
289 .into(),
290 required_power: 3,
291 }),
292 ),
293 (
294 2,
295 Group::V0(GroupV0 {
296 members: [
297 (Identifier::new(identity_id_1), 1),
298 (Identifier::new(identity_id_3), 1),
299 ]
300 .into(),
301 required_power: 1,
302 }),
303 ),
304 ]
305 .into();
306
307 let token_configuration = TokenConfiguration::V0(TokenConfigurationV0 {
308 conventions: TokenConfigurationConventionV0 {
309 localizations: Default::default(),
310 decimals: 8,
311 }
312 .into(),
313 conventions_change_rules: ChangeControlRulesV0::default().into(),
314 base_supply: 100000,
315 max_supply: None,
316 keeps_history: TokenKeepsHistoryRulesV0::default().into(),
317 start_as_paused: false,
318 allow_transfer_to_frozen_balance: true,
319 max_supply_change_rules: ChangeControlRulesV0 {
320 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
321 admin_action_takers: Default::default(),
322 changing_authorized_action_takers_to_no_one_allowed: false,
323 changing_admin_action_takers_to_no_one_allowed: false,
324 self_changing_admin_action_takers_allowed: false,
325 }
326 .into(),
327 distribution_rules: TokenDistributionRulesV0 {
328 perpetual_distribution: Some(TokenPerpetualDistribution::V0(
329 TokenPerpetualDistributionV0 {
330 distribution_type: RewardDistributionType::BlockBasedDistribution {
331 interval: 10,
332 function: DistributionFunction::FixedAmount { amount: 100 },
333 },
334 distribution_recipient: TokenDistributionRecipient::ContractOwner,
335 },
336 )),
337 perpetual_distribution_rules: ChangeControlRulesV0::default().into(),
338 pre_programmed_distribution: None,
339 new_tokens_destination_identity: None,
340 new_tokens_destination_identity_rules: ChangeControlRulesV0::default().into(),
341 minting_allow_choosing_destination: true,
342 minting_allow_choosing_destination_rules: ChangeControlRulesV0::default().into(),
343 change_direct_purchase_pricing_rules: ChangeControlRulesV0 {
344 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
345 admin_action_takers: Default::default(),
346 changing_authorized_action_takers_to_no_one_allowed: false,
347 changing_admin_action_takers_to_no_one_allowed: false,
348 self_changing_admin_action_takers_allowed: false,
349 }
350 .into(),
351 }
352 .into(),
353 marketplace_rules: TokenMarketplaceRulesV0 {
354 trade_mode: Default::default(),
355 trade_mode_change_rules: ChangeControlRulesV0::default().into(),
356 }
357 .into(),
358 manual_minting_rules: ChangeControlRulesV0 {
359 authorized_to_make_change: AuthorizedActionTakers::Group(0),
360 admin_action_takers: Default::default(),
361 changing_authorized_action_takers_to_no_one_allowed: false,
362 changing_admin_action_takers_to_no_one_allowed: false,
363 self_changing_admin_action_takers_allowed: false,
364 }
365 .into(),
366 manual_burning_rules: ChangeControlRulesV0 {
367 authorized_to_make_change: AuthorizedActionTakers::Group(2),
368 admin_action_takers: Default::default(),
369 changing_authorized_action_takers_to_no_one_allowed: false,
370 changing_admin_action_takers_to_no_one_allowed: false,
371 self_changing_admin_action_takers_allowed: false,
372 }
373 .into(),
374 freeze_rules: ChangeControlRulesV0 {
375 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
376 admin_action_takers: Default::default(),
377 changing_authorized_action_takers_to_no_one_allowed: false,
378 changing_admin_action_takers_to_no_one_allowed: false,
379 self_changing_admin_action_takers_allowed: false,
380 }
381 .into(),
382 unfreeze_rules: ChangeControlRulesV0 {
383 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
384 admin_action_takers: Default::default(),
385 changing_authorized_action_takers_to_no_one_allowed: false,
386 changing_admin_action_takers_to_no_one_allowed: false,
387 self_changing_admin_action_takers_allowed: false,
388 }
389 .into(),
390 destroy_frozen_funds_rules: ChangeControlRulesV0 {
391 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
392 admin_action_takers: Default::default(),
393 changing_authorized_action_takers_to_no_one_allowed: false,
394 changing_admin_action_takers_to_no_one_allowed: false,
395 self_changing_admin_action_takers_allowed: false,
396 }
397 .into(),
398 emergency_action_rules: ChangeControlRulesV0 {
399 authorized_to_make_change: AuthorizedActionTakers::ContractOwner,
400 admin_action_takers: Default::default(),
401 changing_authorized_action_takers_to_no_one_allowed: false,
402 changing_admin_action_takers_to_no_one_allowed: false,
403 self_changing_admin_action_takers_allowed: false,
404 }
405 .into(),
406 main_control_group: None,
407 main_control_group_can_be_modified: Default::default(),
408 description: Some("Some token description".to_string()),
409 });
410
411 let mut token_configuration_2 = token_configuration.clone();
413 if let TokenConfiguration::V0(ref mut cfg) = token_configuration_2 {
414 if let TokenDistributionRules::V0(ref mut rules) = cfg.distribution_rules {
415 rules.pre_programmed_distribution = Some(TokenPreProgrammedDistribution::V0(
416 TokenPreProgrammedDistributionV0 {
417 distributions: BTreeMap::from([
418 (
419 1000,
420 BTreeMap::from([
421 (Identifier::new(identity_id_1), 500),
422 (Identifier::new(identity_id_2), 300),
423 ]),
424 ),
425 (
426 5000,
427 BTreeMap::from([(Identifier::new(identity_id_1), 1000)]),
428 ),
429 (
430 10000,
431 BTreeMap::from([
432 (Identifier::new(identity_id_2), 750),
433 (Identifier::new(identity_id_3), 250),
434 ]),
435 ),
436 ]),
437 },
438 ));
439 }
440 }
441
442 let tokens = [
443 (0, token_configuration.clone()),
444 (1, token_configuration),
445 (2, token_configuration_2),
446 ]
447 .into();
448
449 let data_contract = DataContract::V1(DataContractV1 {
450 id: Identifier::new(contract_id),
451 config: DataContractConfig::default_for_version(version)
452 .expect("expected contract config"),
453 version: INITIAL_DATA_CONTRACT_VERSION,
454 owner_id: Identifier::new(identity_id_1),
455 document_types: Default::default(),
456 schema_defs: Default::default(),
457 created_at: None,
458 updated_at: None,
459 created_at_block_height: None,
460 updated_at_block_height: None,
461 created_at_epoch: None,
462 updated_at_epoch: None,
463 groups,
464 tokens,
465 keywords: vec!["cat".into(), "white".into()],
466 description: Some("Some contract description".to_string()),
467 });
468
469 let block_info = BlockInfo::genesis();
470
471 platform
472 .platform
473 .drive
474 .apply_contract(&data_contract, block_info, true, None, None, version)
475 .expect("expected to apply contract");
476
477 for (token_id, id, amount) in [
482 (token_id_0, identity_id_1, 100u64),
483 (token_id_0, identity_id_2, 100),
484 (token_id_1, identity_id_1, 200),
485 (token_id_1, identity_id_3, 100),
486 (token_id_2, identity_id_1, 300),
487 (token_id_2, identity_id_2, 200),
488 ] {
489 platform
490 .platform
491 .drive
492 .token_mint(
493 token_id,
494 id,
495 amount,
496 false,
497 false,
498 &block_info,
499 true,
500 None,
501 version,
502 )
503 .expect("expected to mint tokens");
504 }
505
506 platform
508 .platform
509 .drive
510 .token_freeze(
511 Identifier::new(token_id_0),
512 Identifier::new(identity_id_2),
513 &block_info,
514 true,
515 None,
516 version,
517 )
518 .expect("expected to freeze");
519
520 let status = TokenStatus::V0(TokenStatusV0 { paused: true });
522 platform
523 .platform
524 .drive
525 .token_apply_status(token_id_1, status, &block_info, true, None, version)
526 .expect("expected to apply status");
527
528 platform
530 .platform
531 .drive
532 .token_set_direct_purchase_price(
533 token_id_1,
534 Some(TokenPricingSchedule::SinglePrice(25)),
535 &block_info,
536 true,
537 None,
538 version,
539 )
540 .expect("expected to set direct purchase price");
541
542 let pricing = TokenPricingSchedule::SetPrices(
543 (0..=900)
544 .step_by(100)
545 .map(|amount| (amount, 1000 - amount))
546 .collect(),
547 );
548 platform
549 .platform
550 .drive
551 .token_set_direct_purchase_price(
552 token_id_2,
553 Some(pricing),
554 &block_info,
555 true,
556 None,
557 version,
558 )
559 .expect("expected to set direct purchase price");
560
561 (
562 platform,
563 state,
564 version,
565 contract_id,
566 [token_id_0, token_id_1, token_id_2],
567 [identity_id_1, identity_id_2, identity_id_3],
568 )
569 }
570}