diff --git a/packages/rs-drive-abci/src/query/document_query/mod.rs b/packages/rs-drive-abci/src/query/document_query/mod.rs index cd41f4539b7..ccf8ad91f34 100644 --- a/packages/rs-drive-abci/src/query/document_query/mod.rs +++ b/packages/rs-drive-abci/src/query/document_query/mod.rs @@ -28,7 +28,7 @@ impl Platform { ) -> Result, Error> { let Some(version) = version else { return Ok(QueryValidationResult::new_with_error( - QueryError::DecodingError("could not decode data contracts query".to_string()), + QueryError::DecodingError("could not decode documents query".to_string()), )); }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs index c2506a577b9..2a3245aee80 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs @@ -1,3 +1,4 @@ +pub mod v0; pub mod v1; use versioned_feature_core::{FeatureVersion, FeatureVersionBounds}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v0.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v0.rs new file mode 100644 index 00000000000..bb933d9cbf5 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v0.rs @@ -0,0 +1,339 @@ +use crate::version::drive_abci_versions::drive_abci_query_versions::{ + DriveAbciDocumentQueryHelperVersions, DriveAbciQueryAddressFundsVersions, + DriveAbciQueryDataContractVersions, DriveAbciQueryGroupVersions, + DriveAbciQueryIdentityVersions, DriveAbciQueryPrefundedSpecializedBalancesVersions, + DriveAbciQueryShieldedVersions, DriveAbciQuerySystemVersions, DriveAbciQueryTokenVersions, + DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, +}; +use versioned_feature_core::FeatureVersionBounds; + +/// `DRIVE_ABCI_QUERY_VERSIONS_V0` — query feature-version state before +/// `getDocuments` advanced to V1 (#3633). All fields IDENTICAL to V1 except +/// `document_query`, which pins both `max_version` and `default_current_version` +/// to 0 so clients pinned to a PV using this module emit V0 wire bytes (CBOR +/// `where` / `order_by`, plain `uint32 limit`). This is the version testnet +/// v3.0 HPMNs deserialize. +pub const DRIVE_ABCI_QUERY_VERSIONS_V0: DriveAbciQueryVersions = DriveAbciQueryVersions { + max_returned_elements: 100, + response_metadata: 0, + proofs_query: 0, + document_query: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + document_query_helpers: DriveAbciDocumentQueryHelperVersions { + compute_aggregate_mode_and_check_limit: 0, + }, + prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions { + balance: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + identity_based_queries: DriveAbciQueryIdentityVersions { + identity: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + keys: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identities_contract_keys: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_nonce: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_contract_nonce: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + balance: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identities_balances: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + balance_and_revision: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_by_unique_public_key_hash: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_by_non_unique_public_key_hash: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + token_queries: DriveAbciQueryTokenVersions { + identity_token_balances: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identities_token_balances: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identities_token_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_token_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + token_statuses: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + token_total_supply: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + token_direct_purchase_prices: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + token_pre_programmed_distributions: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + token_perpetual_distribution_last_claim: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + token_contract_info: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + validator_queries: DriveAbciQueryValidatorVersions { + proposed_block_counts_by_evonode_ids: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + proposed_block_counts_by_range: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + data_contract_based_queries: DriveAbciQueryDataContractVersions { + data_contract: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + data_contract_history: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + data_contracts: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + voting_based_queries: DriveAbciQueryVotingVersions { + vote_polls_by_end_date_query: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resource_vote_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resource_voters_for_identity: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resource_identity_vote_status: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resources: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + system: DriveAbciQuerySystemVersions { + version_upgrade_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + version_upgrade_vote_status: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + epoch_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + current_quorums_info: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + partial_status: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + path_elements: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + total_credits_in_platform: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + finalized_epoch_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + group_queries: DriveAbciQueryGroupVersions { + group_info: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + group_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + group_actions: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + group_action_signers: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + shielded_queries: DriveAbciQueryShieldedVersions { + encrypted_notes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + anchors: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + most_recent_anchor: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + pool_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + nullifiers: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + nullifiers_trunk_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + nullifiers_branch_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + recent_nullifier_changes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + recent_compacted_nullifier_changes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + max_encrypted_notes_per_query: 2048, + }, + address_funds_queries: DriveAbciQueryAddressFundsVersions { + addresses_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + address_info: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + addresses_trunk_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + addresses_branch_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + recent_address_balance_changes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + recent_compacted_address_balance_changes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, +}; diff --git a/packages/rs-platform-version/src/version/v1.rs b/packages/rs-platform-version/src/version/v1.rs index 43ee4c7b66b..b3c54787c77 100644 --- a/packages/rs-platform-version/src/version/v1.rs +++ b/packages/rs-platform-version/src/version/v1.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v1::VOTING_VERSION_V1; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v1::DRIVE_ABCI_METHOD_VERSIONS_V1; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v1::DRIVE_ABCI_VALIDATION_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; @@ -38,7 +38,7 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V1, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V1, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v10.rs b/packages/rs-platform-version/src/version/v10.rs index 8f5dc0a6f83..f04b14d341a 100644 --- a/packages/rs-platform-version/src/version/v10.rs +++ b/packages/rs-platform-version/src/version/v10.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v6::DRIVE_ABCI_METHOD_VERSIONS_V6; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v6::DRIVE_ABCI_VALIDATION_VERSIONS_V6; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V10: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V6, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V6, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v11.rs b/packages/rs-platform-version/src/version/v11.rs index bdd50b9ac1c..eb039ad49cf 100644 --- a/packages/rs-platform-version/src/version/v11.rs +++ b/packages/rs-platform-version/src/version/v11.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v7::DRIVE_ABCI_METHOD_VERSIONS_V7; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v7::DRIVE_ABCI_VALIDATION_VERSIONS_V7; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V11: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V7, //update checkpoints change validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V7, // changed for validate_unique_identity_public_key_hashes_in_state withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v2.rs b/packages/rs-platform-version/src/version/v2.rs index 6c3bd2c5c29..93cd7b07232 100644 --- a/packages/rs-platform-version/src/version/v2.rs +++ b/packages/rs-platform-version/src/version/v2.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v1::VOTING_VERSION_V1; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v1::DRIVE_ABCI_METHOD_VERSIONS_V1; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v2::DRIVE_ABCI_VALIDATION_VERSIONS_V2; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; @@ -38,7 +38,7 @@ pub const PLATFORM_V2: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V1, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V2, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v3.rs b/packages/rs-platform-version/src/version/v3.rs index dd82d4aaed3..c125b94ff9b 100644 --- a/packages/rs-platform-version/src/version/v3.rs +++ b/packages/rs-platform-version/src/version/v3.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v2::DRIVE_ABCI_METHOD_VERSIONS_V2; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v2::DRIVE_ABCI_VALIDATION_VERSIONS_V2; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; @@ -44,7 +44,7 @@ pub const PLATFORM_V3: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V2, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V2, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v4.rs b/packages/rs-platform-version/src/version/v4.rs index d47ce1b5f09..dba41251e96 100644 --- a/packages/rs-platform-version/src/version/v4.rs +++ b/packages/rs-platform-version/src/version/v4.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v3::DRIVE_ABCI_METHOD_VERSIONS_V3; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v3::DRIVE_ABCI_VALIDATION_VERSIONS_V3; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V4: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V3, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V3, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v5.rs b/packages/rs-platform-version/src/version/v5.rs index 31bbf7852fb..3c288cfe63d 100644 --- a/packages/rs-platform-version/src/version/v5.rs +++ b/packages/rs-platform-version/src/version/v5.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v4::DRIVE_ABCI_METHOD_VERSIONS_V4; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v3::DRIVE_ABCI_VALIDATION_VERSIONS_V3; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V5: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V4, // changed to v4 validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V3, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v6.rs b/packages/rs-platform-version/src/version/v6.rs index e13ba041a20..7d948da6f00 100644 --- a/packages/rs-platform-version/src/version/v6.rs +++ b/packages/rs-platform-version/src/version/v6.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v4::DRIVE_ABCI_METHOD_VERSIONS_V4; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v4::DRIVE_ABCI_VALIDATION_VERSIONS_V4; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V6: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V4, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V4, // Changed to version 4 withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v7.rs b/packages/rs-platform-version/src/version/v7.rs index 568975a49bd..09755d462e1 100644 --- a/packages/rs-platform-version/src/version/v7.rs +++ b/packages/rs-platform-version/src/version/v7.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v4::DRIVE_ABCI_METHOD_VERSIONS_V4; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v5::DRIVE_ABCI_VALIDATION_VERSIONS_V5; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V7: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V4, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V5, // <--- changed to V5 withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v8.rs b/packages/rs-platform-version/src/version/v8.rs index 2bb4c03e4fa..2096142ac18 100644 --- a/packages/rs-platform-version/src/version/v8.rs +++ b/packages/rs-platform-version/src/version/v8.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v5::DRIVE_ABCI_METHOD_VERSIONS_V5; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v5::DRIVE_ABCI_VALIDATION_VERSIONS_V5; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -43,7 +43,7 @@ pub const PLATFORM_V8: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V5, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V5, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/src/version/v9.rs b/packages/rs-platform-version/src/version/v9.rs index bb4c1d5e918..a27803f6da8 100644 --- a/packages/rs-platform-version/src/version/v9.rs +++ b/packages/rs-platform-version/src/version/v9.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v6::DRIVE_ABCI_METHOD_VERSIONS_V6; -use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v0::DRIVE_ABCI_QUERY_VERSIONS_V0; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_validation_versions::v6::DRIVE_ABCI_VALIDATION_VERSIONS_V6; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; @@ -39,7 +39,7 @@ pub const PLATFORM_V9: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V6, // changed because of the genesis state validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V6, // changed withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-sdk-ffi/src/data_contract/queries/history.rs b/packages/rs-sdk-ffi/src/data_contract/queries/history.rs index 65077556546..293e2344f05 100644 --- a/packages/rs-sdk-ffi/src/data_contract/queries/history.rs +++ b/packages/rs-sdk-ffi/src/data_contract/queries/history.rs @@ -26,8 +26,8 @@ impl dash_sdk::platform::Query, ) -> Result { use dash_sdk::dapi_grpc::platform::v0::get_data_contract_history_request::{ @@ -41,7 +41,7 @@ impl dash_sdk::platform::Query for EvonodesProposedEpochBlocksByIdsQuery { fn query( - self, - prove: bool, + &self, + settings: &dash_sdk::platform::QuerySettings<'_>, ) -> Result< dash_sdk::dapi_grpc::platform::v0::GetEvonodesProposedEpochBlocksByIdsRequest, dash_sdk::Error, @@ -171,10 +171,10 @@ impl epoch: self.epoch, ids: self .pro_tx_hashes - .into_iter() - .map(|hash| AsRef::<[u8]>::as_ref(&hash).to_vec()) + .iter() + .map(|hash| AsRef::<[u8]>::as_ref(hash).to_vec()) .collect(), - prove, + prove: settings.prove, })), }; diff --git a/packages/rs-sdk-ffi/src/evonode/queries/proposed_epoch_blocks_by_range.rs b/packages/rs-sdk-ffi/src/evonode/queries/proposed_epoch_blocks_by_range.rs index 7605cfac138..31b880485e4 100644 --- a/packages/rs-sdk-ffi/src/evonode/queries/proposed_epoch_blocks_by_range.rs +++ b/packages/rs-sdk-ffi/src/evonode/queries/proposed_epoch_blocks_by_range.rs @@ -173,8 +173,8 @@ impl > for EvonodesProposedEpochBlocksByRangeQuery { fn query( - self, - prove: bool, + &self, + settings: &dash_sdk::platform::QuerySettings<'_>, ) -> Result< dash_sdk::dapi_grpc::platform::v0::GetEvonodesProposedEpochBlocksByRangeRequest, dash_sdk::Error, @@ -186,13 +186,14 @@ impl }, }; - let start = if let Some(start_after) = self.start_after { + let start = if let Some(start_after) = self.start_after.as_ref() { Some(Start::StartAfter( - AsRef::<[u8]>::as_ref(&start_after).to_vec(), + AsRef::<[u8]>::as_ref(start_after).to_vec(), )) } else { self.start_at - .map(|start_at| Start::StartAt(AsRef::<[u8]>::as_ref(&start_at).to_vec())) + .as_ref() + .map(|start_at| Start::StartAt(AsRef::<[u8]>::as_ref(start_at).to_vec())) }; let request = @@ -202,7 +203,7 @@ impl epoch: self.epoch, limit: None, // Limit is handled by LimitQuery wrapper start, - prove, + prove: settings.prove, }, )), }; diff --git a/packages/rs-sdk-ffi/src/types.rs b/packages/rs-sdk-ffi/src/types.rs index 0f57d4bda63..ce5e7eb20a3 100644 --- a/packages/rs-sdk-ffi/src/types.rs +++ b/packages/rs-sdk-ffi/src/types.rs @@ -56,6 +56,11 @@ pub use dash_network::Network; /// `Copy` is intentionally **not** derived: duplicating raw pointers via implicit /// copies risks use-after-free if the original string is freed while a copy is /// still in use. +// TODO(CMT-007, #3711): FFI cannot express initial protocol-version seed for +// older-network interop. Deferred — pending core SDK fix for the broader +// "first-request-on-default-SDK uses latest() wire shape" issue (CMT-005). +// Once SDK auto-detects PV before encoding the first request, FFI inherits +// it without API surface changes. #[repr(C)] pub struct DashSDKConfig { /// Network to connect to diff --git a/packages/rs-sdk/src/mock/sdk.rs b/packages/rs-sdk/src/mock/sdk.rs index 9e52c297d24..f1c74b10e37 100644 --- a/packages/rs-sdk/src/mock/sdk.rs +++ b/packages/rs-sdk/src/mock/sdk.rs @@ -5,7 +5,7 @@ use super::MockResponse; use crate::{ platform::{ types::{evonode::EvoNode, identity::IdentityRequest}, - DocumentQuery, Fetch, FetchMany, Query, + Fetch, FetchMany, Query, }, sync::block_on, Error, Sdk, @@ -42,7 +42,6 @@ use tokio::sync::{Mutex, OwnedMutexGuard}; #[derive(Debug)] pub struct MockDashPlatformSdk { from_proof_expectations: BTreeMap>, - platform_version: &'static PlatformVersion, dapi: Arc>, sdk: ArcSwapOption, } @@ -66,10 +65,9 @@ impl MockDashPlatformSdk { /// ## Note /// /// You have to call [MockDashPlatformSdk::set_sdk()] to set sdk, otherwise Mock SDK will panic. - pub(crate) fn new(version: &'static PlatformVersion, dapi: Arc>) -> Self { + pub(crate) fn new(dapi: Arc>) -> Self { Self { from_proof_expectations: Default::default(), - platform_version: version, dapi, sdk: ArcSwapOption::new(None), } @@ -79,8 +77,21 @@ impl MockDashPlatformSdk { self.sdk.store(Some(Arc::new(sdk))); } + /// Returns the current `PlatformVersion` from the outer [`Sdk`]'s + /// auto-detect-aware atomic. Both request-encode (`sdk.query_settings()`) + /// and proof-decode (`parse_proof_with_metadata`) read through this + /// single source, so a mock ratchet from response metadata is visible + /// to both paths. + /// + /// ## Panics + /// + /// Panics when sdk is not set during initialization. pub(crate) fn version<'v>(&self) -> &'v PlatformVersion { - self.platform_version + if let Some(sdk) = self.sdk.load().as_ref() { + sdk.version() + } else { + panic!("sdk must be set when creating mock ") + } } /// Load all expectations from files in a directory asynchronously. @@ -133,7 +144,9 @@ impl MockDashPlatformSdk { let request_type = basename.split('_').nth(1).unwrap_or_default(); match request_type { - "DocumentQuery" => load_expectation::(&mut dapi, filename)?, + "GetDocumentsRequest" => { + load_expectation::(&mut dapi, filename)? + } "GetEpochsInfoRequest" => { load_expectation::(&mut dapi, filename)? } @@ -315,7 +328,7 @@ impl MockDashPlatformSdk { /// assert_eq!(retrieved, expected); /// # }); /// ``` - pub async fn expect_fetch::Request>>( + pub async fn expect_fetch::Query>>( &mut self, query: Q, object: Option, @@ -323,8 +336,9 @@ impl MockDashPlatformSdk { where <::Request as TransportRequest>::Response: Default, { - let grpc_request = query.query(self.prove()).expect("query must be correct"); - self.expect(grpc_request, object).await?; + let (rich, wire) = + self.encode_rich_to_wire::::Query, ::Request>(query); + self.expect(&rich, wire, object).await?; Ok(self) } @@ -335,11 +349,11 @@ impl MockDashPlatformSdk { pub async fn remove_fetch_expectation(&mut self, query: Q) -> bool where O: Fetch, - Q: Query<::Request>, - ::Request: TransportRequest, + Q: Query<::Query>, { - let grpc_request = query.query(self.prove()).expect("query must be correct"); - self.remove(grpc_request).await + let (rich, wire) = + self.encode_rich_to_wire::::Query, ::Request>(query); + self.remove(&rich, wire).await } /// Expect a [FetchMany] request and return provided object. @@ -375,7 +389,7 @@ impl MockDashPlatformSdk { pub async fn expect_fetch_many< K: Ord, O: FetchMany, - Q: Query<>::Request>, + Q: Query<>::Query>, R, >( &mut self, @@ -386,51 +400,84 @@ impl MockDashPlatformSdk { R: FromIterator<(K, Option)> + MockResponse + FromProof< - >::Request, - Request = >::Request, + >::Query, + Request = >::Query, Response = <>::Request as TransportRequest>::Response, > + Sync + Send + Default, <>::Request as TransportRequest>::Response: Default, { - let grpc_request = query.query(self.prove()).expect("query must be correct"); - self.expect(grpc_request, objects).await?; + let (rich, wire) = self + .encode_rich_to_wire::>::Query, >::Request>( + query, + ); + self.expect(&rich, wire, objects).await?; Ok(self) } + /// Encode a user-facing `query` first into its rich form (`R`) and + /// then into its wire form (`W`), both against the SDK's current + /// `QuerySettings`. Returns `(rich, wire)` for use as proof-mock / + /// DAPI-mock expectation keys. + /// + /// ## Panics + /// + /// INTENTIONAL(SEC-001): test-harness fail-fast — encoder errors + /// for V1-only `DocumentQuery` features against a V0 + /// `PlatformVersion` crash the test setup loudly rather than + /// silently propagate. Panics also if `set_sdk` was not called. + fn encode_rich_to_wire(&self, query: Q) -> (R, W) + where + Q: Query, + R: Query + Mockable, + W: TransportRequest, + { + let sdk_guard = self.sdk.load(); + let sdk = sdk_guard + .as_ref() + .expect("sdk must be set when creating mock"); + let settings = sdk.query_settings(); + let rich: R = query.query(&settings).expect("query must be correct"); + let wire: W = rich.query(&settings).expect("wire encoding must succeed"); + (rich, wire) + } + /// Save expectations for a request. - async fn expect( + /// + /// `rich_request` is the user-facing query (what [`FromProof`] binds to) and seeds + /// the proof-mock cache key. `wire_request` is the proto that flows over the wire + /// and seeds the DAPI executor mock. For non-versioned operations both arguments + /// are the same value; for documents the rich form is [`DocumentQuery`] and the + /// wire is [`GetDocumentsRequest`]. + async fn expect( &mut self, - grpc_request: I, + rich_request: &R, + wire_request: W, returned_object: Option, ) -> Result<(), Error> where - I::Response: Default, + W::Response: Default, { - let key = Key::new(&grpc_request); + let key = Key::new(rich_request); - // detect duplicates if self.from_proof_expectations.contains_key(&key) { return Err(MockError::MockExpectationConflict(format!( "proof expectation key {} already defined for {} request: {:?}", key, - std::any::type_name::(), - grpc_request + std::any::type_name::(), + rich_request )) .into()); } - // This expectation will work for from_proof self.from_proof_expectations .insert(key, returned_object.mock_serialize(self)); - // This expectation will work for execute let mut dapi_guard = self.dapi.lock().await; - // We don't really care about the response, as it will be mocked by from_proof, so we provide default() dapi_guard.expect( - &grpc_request, + &wire_request, &Ok(ExecutionResponse { inner: Default::default(), retries: 0, @@ -442,12 +489,16 @@ impl MockDashPlatformSdk { } /// Remove expectations for a request. - async fn remove(&mut self, grpc_request: I) -> bool { - let key = Key::new(&grpc_request); + async fn remove( + &mut self, + rich_request: &R, + wire_request: W, + ) -> bool { + let key = Key::new(rich_request); let removed_from_proof = self.from_proof_expectations.remove(&key).is_some(); let mut dapi_guard = self.dapi.lock().await; - let removed_from_dapi = dapi_guard.remove(&grpc_request); + let removed_from_dapi = dapi_guard.remove(&wire_request); removed_from_proof || removed_from_dapi } diff --git a/packages/rs-sdk/src/platform.rs b/packages/rs-sdk/src/platform.rs index 36d42444f4c..006cab205c2 100644 --- a/packages/rs-sdk/src/platform.rs +++ b/packages/rs-sdk/src/platform.rs @@ -18,6 +18,7 @@ mod fetch_unproved; pub mod group_actions; pub mod identities_contract_keys_query; pub mod query; +pub mod query_settings; #[cfg(feature = "shielded")] pub mod shielded; pub mod tokens; @@ -46,4 +47,5 @@ pub use { RecentAddressBalanceChangesQuery, RecentCompactedAddressBalanceChangesQuery, DEFAULT_EPOCH_QUERY_LIMIT, }, + query_settings::QuerySettings, }; diff --git a/packages/rs-sdk/src/platform/documents/document_average.rs b/packages/rs-sdk/src/platform/documents/document_average.rs index 0e4f923a0ec..340b7ca1a4e 100644 --- a/packages/rs-sdk/src/platform/documents/document_average.rs +++ b/packages/rs-sdk/src/platform/documents/document_average.rs @@ -102,7 +102,8 @@ impl FromProof for DocumentAverage { } impl Fetch for DocumentAverage { - type Request = super::document_query::DocumentQuery; + type Query = super::document_query::DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } #[cfg(test)] diff --git a/packages/rs-sdk/src/platform/documents/document_count.rs b/packages/rs-sdk/src/platform/documents/document_count.rs index 08b36c33eb3..8f46f8c9c90 100644 --- a/packages/rs-sdk/src/platform/documents/document_count.rs +++ b/packages/rs-sdk/src/platform/documents/document_count.rs @@ -49,5 +49,6 @@ impl FromProof for DocumentCount { } impl Fetch for DocumentCount { - type Request = DocumentQuery; + type Query = DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } diff --git a/packages/rs-sdk/src/platform/documents/document_query.rs b/packages/rs-sdk/src/platform/documents/document_query.rs index 9105aa73527..ecab8f26daf 100644 --- a/packages/rs-sdk/src/platform/documents/document_query.rs +++ b/packages/rs-sdk/src/platform/documents/document_query.rs @@ -2,8 +2,9 @@ use std::sync::Arc; +use crate::platform::Fetch; use crate::{error::Error, sdk::Sdk}; -use dapi_grpc::platform::v0::get_documents_request::Version::V1; +use dapi_grpc::platform::v0::get_documents_request::Version::{V0, V1}; use dapi_grpc::platform::v0::{ self as platform_proto, get_documents_request::{ @@ -11,16 +12,17 @@ use dapi_grpc::platform::v0::{ get_documents_request_v0::Start, get_documents_request_v1::{select, Select as ProtoSelect, Start as V1Start}, having_aggregate, having_clause, having_ranking, order_clause, - DocumentFieldValue as ProtoDocumentFieldValue, GetDocumentsRequestV1, - HavingAggregate as ProtoHavingAggregate, HavingClause as ProtoHavingClause, - HavingRanking as ProtoHavingRanking, OrderClause as ProtoOrderClause, - WhereClause as ProtoWhereClause, WhereOperator as ProtoWhereOperator, + DocumentFieldValue as ProtoDocumentFieldValue, GetDocumentsRequestV0, + GetDocumentsRequestV1, HavingAggregate as ProtoHavingAggregate, + HavingClause as ProtoHavingClause, HavingRanking as ProtoHavingRanking, + OrderClause as ProtoOrderClause, WhereClause as ProtoWhereClause, + WhereOperator as ProtoWhereOperator, }, GetDocumentsRequest, Proof, ResponseMetadata, }; use dash_context_provider::ContextProvider; use dpp::dashcore::Network; -use dpp::version::PlatformVersion; +use dpp::version::{PlatformVersion, TryFromPlatformVersioned}; use dpp::{ data_contract::{ accessors::v0::DataContractV0Getters, document_type::accessors::DocumentTypeV0Getters, @@ -36,11 +38,6 @@ use drive::query::{ SelectFunction, SelectProjection, WhereClause, WhereOperator, }; use drive_proof_verifier::{types::Documents, FromProof}; -use rs_dapi_client::transport::{ - AppliedRequestSettings, BoxFuture, TransportError, TransportRequest, -}; - -use crate::platform::Fetch; // TODO: remove DocumentQuery once ContextProvider that provides data contracts is merged. @@ -267,46 +264,16 @@ impl DocumentQuery { self.limit = limit; self } -} - -impl TransportRequest for DocumentQuery { - type Client = ::Client; - type Response = ::Response; - const SETTINGS_OVERRIDES: rs_dapi_client::RequestSettings = - ::SETTINGS_OVERRIDES; - - fn request_name(&self) -> &'static str { - "GetDocumentsRequest" - } - - fn method_name(&self) -> &'static str { - "get_documents" - } - fn execute_transport<'c>( + /// Convert into the wire-format [`GetDocumentsRequest`] using a + /// specific [`PlatformVersion`] to pick V0 vs V1. The dispatch + /// boundary is the document_query feature-version on the + /// platform_version: `0` → V0, `1` → V1. + pub fn try_into_request_for_version( self, - client: &'c mut Self::Client, - settings: &AppliedRequestSettings, - ) -> BoxFuture<'c, Result> { - // `TryFrom for GetDocumentsRequest` became - // fallible once `where_clause_to_proto` / `having_clause_to_proto` - // / `value_to_proto` started rejecting `Value` variants - // that have no wire-format counterpart (`Map`, future - // `Value` additions, …). Propagate the conversion failure - // as a `TransportError::Grpc(Status::invalid_argument(...))` - // so the SDK surfaces a normal request error instead of - // panicking the process. - let request: GetDocumentsRequest = match self.try_into() { - Ok(r) => r, - Err(e) => { - let status = dapi_grpc::tonic::Status::invalid_argument(format!( - "DocumentQuery contains values that can't be encoded on the v1 \ - wire: {e}" - )); - return Box::pin(async move { Err(TransportError::Grpc(status)) }); - } - }; - request.execute_transport(client, settings) + platform_version: &PlatformVersion, + ) -> Result { + GetDocumentsRequest::try_from_platform_versioned(self, platform_version) } } @@ -381,11 +348,22 @@ impl FromProof for drive_proof_verifier::types::Documents { } } -impl TryFrom for platform_proto::GetDocumentsRequest { +/// Version-aware encoder. The dispatch is driven by the +/// `drive_abci.query.document_query` feature-version on +/// [`PlatformVersion`]: `0` → V0 wire (used by v3.0 testnet), `1` → +/// V1 wire (introduced in v3.1). +/// +/// V0 lacks `selects` / `group_by` / `having` / `offset` and the +/// optional-limit semantics — callers that set those features get +/// `Error::Config` with a clear "requires Platform v3.1+" message +/// rather than a silently-truncated request. +impl TryFromPlatformVersioned for GetDocumentsRequest { type Error = Error; - fn try_from(dapi_request: DocumentQuery) -> Result { - // `try_from` owns `dapi_request` — destructure once and - // consume the owned vectors below (no `.clone()` per field). + + fn try_from_platform_versioned( + value: DocumentQuery, + platform_version: &PlatformVersion, + ) -> Result { let DocumentQuery { select, data_contract, @@ -396,67 +374,204 @@ impl TryFrom for platform_proto::GetDocumentsRequest { order_by_clauses, limit, start, - } = dapi_request; - - let where_clauses = where_clauses - .into_iter() - .map(where_clause_to_proto) - .collect::, _>>()?; - let order_by = order_by_clauses - .into_iter() - .map(order_clause_to_proto) - .collect(); - let having = having - .into_iter() - .map(having_clause_to_proto) - .collect::, _>>()?; - // `limit: u32` with `0` sentinel → `optional uint32` on the - // V1 wire. `None` lets the server apply its own default; - // explicit `0` would be a strange "return zero rows" request. - let limit = if limit == 0 { None } else { Some(limit) }; - // V0 and V1 ship separate `Start` enums even though the - // shape is identical. Translate at the wire boundary so the - // `DocumentQuery.start` field stays stable for callers - // already using the V0 type. - let start_v1 = start.map(|s| match s { - Start::StartAfter(b) => V1Start::StartAfter(b), - Start::StartAt(b) => V1Start::StartAt(b), - }); - - //todo: transform this into PlatformVersionedTryFrom - Ok(GetDocumentsRequest { - version: Some(V1(GetDocumentsRequestV1 { - data_contract_id: data_contract.id().to_vec(), - document_type: document_type_name, + } = value; + + let feature_version = platform_version + .drive_abci + .query + .document_query + .default_current_version; + + tracing::debug!( + target: "dash_sdk::query_encoder", + feature_version, + protocol_version = platform_version.protocol_version, + "encoding GetDocumentsRequest" + ); + + match feature_version { + 0 => encode_v0( + data_contract.id().to_vec(), + document_type_name, + where_clauses, + order_by_clauses, + limit, + start, + &select, + &group_by, + &having, + ), + 1 => encode_v1( + data_contract.id().to_vec(), + document_type_name, where_clauses, - order_by, + order_by_clauses, limit, - // Document fetch always proves via this conversion. - // Count fetch uses the same wire shape; both paths - // go through the `FromProof` decoders which expect - // the `Proof(...)` response variant. `SdkBuilder:: - // with_proofs(false)` is consequently a no-op for - // both — see the blanket `Query for T` impl in - // `packages/rs-sdk/src/platform/query.rs` for the - // `tracing::warn!` emitted at fetch time when proofs - // are disabled. - prove: true, - start: start_v1, - // `repeated Select selects` on the wire — single - // projection wraps in a one-element vec; the SDK's - // `DocumentQuery` carries a single - // `SelectProjection` because multi-projection is - // wire-only today. - selects: vec![select_to_proto(select)], + start, + select, group_by, having, - // `offset` is wire-reserved for future row-based - // pagination; the SDK doesn't surface it yet, so - // we always emit `None` here. - offset: None, - })), - }) + ), + n => Err(Error::Config(format!( + "GetDocumentsRequest wire encoder does not support feature_version={n} \ + (drive_abci.query.document_query) on PlatformVersion v{}", + platform_version.protocol_version + ))), + } + } +} + +#[allow(clippy::too_many_arguments)] +fn encode_v1( + data_contract_id: Vec, + document_type: String, + where_clauses: Vec, + order_by_clauses: Vec, + limit: u32, + start: Option, + select: SelectProjection, + group_by: Vec, + having: Vec, +) -> Result { + let where_clauses = where_clauses + .into_iter() + .map(where_clause_to_proto) + .collect::, _>>()?; + let order_by = order_by_clauses + .into_iter() + .map(order_clause_to_proto) + .collect(); + let having = having + .into_iter() + .map(having_clause_to_proto) + .collect::, _>>()?; + // `limit: u32` with `0` sentinel → `optional uint32` on the V1 + // wire. `None` lets the server apply its own default; explicit + // `0` would be a strange "return zero rows" request. + let limit = if limit == 0 { None } else { Some(limit) }; + // V0 and V1 ship separate `Start` enums even though the shape + // is identical. Translate at the wire boundary so the + // `DocumentQuery.start` field stays stable for callers already + // using the V0 type. + let start_v1 = start.map(|s| match s { + Start::StartAfter(b) => V1Start::StartAfter(b), + Start::StartAt(b) => V1Start::StartAt(b), + }); + + Ok(GetDocumentsRequest { + version: Some(V1(GetDocumentsRequestV1 { + data_contract_id, + document_type, + where_clauses, + order_by, + limit, + // Document fetch always proves via this conversion. + // Count fetch uses the same wire shape; both paths go + // through the `FromProof` decoders which expect the + // `Proof(...)` response variant. `SdkBuilder::with_proofs(false)` + // is consequently a no-op for both — see the blanket + // `Query for T` impl in `packages/rs-sdk/src/platform/query.rs` + // for the `tracing::warn!` emitted at fetch time when + // proofs are disabled. + prove: true, + start: start_v1, + // `repeated Select selects` on the wire — single + // projection wraps in a one-element vec; the SDK's + // `DocumentQuery` carries a single `SelectProjection` + // because multi-projection is wire-only today. + selects: vec![select_to_proto(select)], + group_by, + having, + // `offset` is wire-reserved for future row-based + // pagination; the SDK doesn't surface it yet, so we + // always emit `None` here. + offset: None, + })), + }) +} + +#[allow(clippy::too_many_arguments)] +fn encode_v0( + data_contract_id: Vec, + document_type: String, + where_clauses: Vec, + order_by_clauses: Vec, + limit: u32, + start: Option, + select: &SelectProjection, + group_by: &[String], + having: &[HavingClause], +) -> Result { + // V0 only carries plain `getDocuments` semantics — reject the + // v1-only SQL-shaped surfaces with a typed error rather than + // letting the server reject them after a round-trip. + if !matches!(select.function, SelectFunction::Documents) { + return Err(Error::Config(format!( + "select={:?} requires Platform v3.1+ (V1 documents wire); pin/upgrade \ + to a v3.1+ network or rebuild the query with SelectProjection::documents()", + select.function + ))); + } + if !group_by.is_empty() { + return Err(Error::Config( + "group_by requires Platform v3.1+ (V1 documents wire); not supported on V0".to_string(), + )); + } + if !having.is_empty() { + return Err(Error::Config( + "having clauses require Platform v3.1+ (V1 documents wire); not supported on V0" + .to_string(), + )); } + + // V0 carries CBOR-serialized arrays of clause components. The + // server decodes them via `ciborium::de::from_reader` into a + // `Value`, then expects `Value::Array(clauses)` where each + // inner clause is `[field_text, operator_text, value]` (where) + // or `[field_text, "asc"|"desc"]` (order_by). Build the same + // shape via the existing `From for Value` / + // `From for Value` impls, then serialize the + // top-level array. + let where_bytes = if where_clauses.is_empty() { + Vec::new() + } else { + let where_value = Value::Array(where_clauses.into_iter().map(Value::from).collect()); + where_value.to_cbor_buffer().map_err(|e| { + Error::Protocol(dpp::ProtocolError::EncodingError(format!( + "failed to CBOR-encode v0 where clauses: {e}" + ))) + })? + }; + let order_by_bytes = if order_by_clauses.is_empty() { + Vec::new() + } else { + let order_value = Value::Array(order_by_clauses.into_iter().map(Value::from).collect()); + order_value.to_cbor_buffer().map_err(|e| { + Error::Protocol(dpp::ProtocolError::EncodingError(format!( + "failed to CBOR-encode v0 order_by clauses: {e}" + ))) + })? + }; + + Ok(GetDocumentsRequest { + version: Some(V0(GetDocumentsRequestV0 { + data_contract_id, + document_type, + r#where: where_bytes, + order_by: order_by_bytes, + // V0's `limit` is a plain u32 with 0 = "server default". + // V1's `optional uint32` keeps 0 as a structurally + // meaningless explicit-zero; we translate by clamping + // to 0 only when the caller meant "unset". + limit, + start, + // `prove: true` hardcoded — same rationale as `encode_v1`: + // document fetch always proves; `SdkBuilder::with_proofs(false)` + // is a no-op for this path because the `FromProof` decoder + // expects the `Proof(...)` response variant. + prove: true, + })), + }) } impl<'a> From<&'a DriveDocumentQuery<'a>> for DocumentQuery { @@ -826,3 +941,20 @@ fn value_to_proto_at_depth(value: Value, depth: u8) -> Result for DocumentQuery { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + GetDocumentsRequest::try_from_platform_versioned(self.clone(), settings.protocol_version) + } +} diff --git a/packages/rs-sdk/src/platform/documents/document_split_averages.rs b/packages/rs-sdk/src/platform/documents/document_split_averages.rs index 078910ee882..f15f1695151 100644 --- a/packages/rs-sdk/src/platform/documents/document_split_averages.rs +++ b/packages/rs-sdk/src/platform/documents/document_split_averages.rs @@ -59,5 +59,6 @@ impl FromProof for DocumentSplitAverages { } impl Fetch for DocumentSplitAverages { - type Request = super::document_query::DocumentQuery; + type Query = super::document_query::DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } diff --git a/packages/rs-sdk/src/platform/documents/document_split_counts.rs b/packages/rs-sdk/src/platform/documents/document_split_counts.rs index d0221e0d33c..79fb3455354 100644 --- a/packages/rs-sdk/src/platform/documents/document_split_counts.rs +++ b/packages/rs-sdk/src/platform/documents/document_split_counts.rs @@ -64,5 +64,6 @@ impl FromProof for DocumentSplitCounts { } impl Fetch for DocumentSplitCounts { - type Request = DocumentQuery; + type Query = DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } diff --git a/packages/rs-sdk/src/platform/documents/document_split_sums.rs b/packages/rs-sdk/src/platform/documents/document_split_sums.rs index 9f692a6cc4b..fc5d1203304 100644 --- a/packages/rs-sdk/src/platform/documents/document_split_sums.rs +++ b/packages/rs-sdk/src/platform/documents/document_split_sums.rs @@ -56,5 +56,6 @@ impl FromProof for DocumentSplitSums { } impl Fetch for DocumentSplitSums { - type Request = super::document_query::DocumentQuery; + type Query = super::document_query::DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } diff --git a/packages/rs-sdk/src/platform/documents/document_sum.rs b/packages/rs-sdk/src/platform/documents/document_sum.rs index 9c271a670b9..c4265ec9ece 100644 --- a/packages/rs-sdk/src/platform/documents/document_sum.rs +++ b/packages/rs-sdk/src/platform/documents/document_sum.rs @@ -87,7 +87,8 @@ impl FromProof for DocumentSum { } impl Fetch for DocumentSum { - type Request = super::document_query::DocumentQuery; + type Query = super::document_query::DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } #[cfg(test)] diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 520e442b13b..f153936096a 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -6,11 +6,15 @@ //! ## Traits //! - [Fetch]: An asynchronous trait that defines how to fetch data from Platform. //! It requires the implementing type to also implement [Debug] and [FromProof] -//! traits. The associated [`Fetch::Request`] type needs to implement [TransportRequest]. +//! traits. The associated [`Fetch::Query`] / [`Fetch::Request`] types split the +//! user-facing query (what `FromProof` consumes) from the wire-encoded proto +//! (what flows over the network); for non-versioned operations they alias to +//! the same proto type, for versioned ones (today: documents) they differ. use crate::mock::MockResponse; use crate::sync::retry; use crate::{error::Error, platform::query::Query, Sdk}; +use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::{self as platform_proto, Proof, ResponseMetadata}; use dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_moment::RewardDistributionMoment; use dpp::identity::identities_contract_keys::IdentitiesContractKeys; @@ -59,17 +63,29 @@ where + Debug + MockResponse + FromProof< - ::Request, - Request = ::Request, + ::Query, + Request = ::Query, Response = <::Request as DapiRequest>::Response, >, { - /// Type of request used to fetch data from Platform. - /// - /// Most likely, one of the types defined in [`dapi_grpc::platform::v0`]. - /// - /// This type must implement [`TransportRequest`]. - type Request: TransportRequest + Into<::Request>>::Request>; + /// User-facing query type — the rich form that callers hand to + /// the SDK and that [`FromProof`] binds to. For non-versioned + /// operations this aliases to [`Self::Request`] (the wire proto); + /// for versioned ones (e.g. documents) it stays the rich pre-wire + /// form (e.g. [`DocumentQuery`]) so the proof verifier keeps its + /// context (data contract, document type) without re-fetching. + // + // Associated-type defaults are nightly-only (RFC 2532); each impl + // must spell out `type Query = Self::Request;` when the rich and + // wire forms coincide. + type Query: Query<::Request> + Mockable + Clone + Debug + Send + Sync; + + /// Wire-encoded request that hits the network. Implements + /// [`TransportRequest`]. For non-versioned operations + /// `Self::Query = Self::Request`; for versioned ones the + /// [`Query::query`] impl on [`Self::Query`] performs the + /// protocol-version-aware wire encoding using `&Sdk`. + type Request: TransportRequest; /// Fetch single object from Platform. /// @@ -91,7 +107,7 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [Error] instances. - async fn fetch::Request>>( + async fn fetch::Query>>( sdk: &Sdk, query: Q, ) -> Result, Error> { @@ -119,7 +135,7 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [Error] instances. - async fn fetch_with_metadata::Request>>( + async fn fetch_with_metadata::Query>>( sdk: &Sdk, query: Q, settings: Option, @@ -153,29 +169,43 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [Error] instances. - async fn fetch_with_metadata_and_proof::Request>>( + async fn fetch_with_metadata_and_proof::Query>>( sdk: &Sdk, query: Q, - settings: Option, + request_settings: Option, ) -> Result<(Option, ResponseMetadata, Proof), Error> { - let request: &::Request = &query.query(sdk.prove())?; + let settings = sdk.query_settings(); + let owned_rich: ::Query = query.query(&settings)?; + // INTENTIONAL(CMT-008, #3711): For the common case `Self::Query = Self::Request`, + // the blanket `Query for T` impl turns the `query.query(settings)` step into a + // pure clone of the same owned request. Real but micro-cost (~63 impls hit + // this path). Specializing via a `fn encode_request_owned()` default method on + // `Fetch` would eliminate the clone — deferred as future-perf work; trait shape + // is intentionally uniform for now. + let owned_wire: ::Request = owned_rich.query(&settings)?; + let rich = &owned_rich; + let wire = &owned_wire; let fut = |settings: RequestSettings| async move { let ExecutionResponse { address, retries, inner: response, - } = request + } = wire .clone() .execute(sdk, settings) .await .map_err(|execution_error| execution_error.inner_into())?; let object_type = std::any::type_name::().to_string(); - tracing::trace!(request = ?request, response = ?response, ?address, retries, object_type, "fetched object from platform"); + tracing::trace!(request = ?wire, response = ?response, ?address, retries, object_type, "fetched object from platform"); let (object, response_metadata, proof): (Option, ResponseMetadata, Proof) = sdk - .parse_proof_with_metadata_and_proof(request.clone(), response) + .parse_proof_with_metadata_and_proof::<::Query, Self>( + rich.clone(), + response, + wire.method_name(), + ) .await .map_err(|e| ExecutionError { inner: e, @@ -194,11 +224,13 @@ where }) }; - let settings = sdk + let retry_settings = sdk .dapi_client_settings - .override_by(settings.unwrap_or_default()); + .override_by(request_settings.unwrap_or_default()); - retry(sdk.address_list(), settings, fut).await.into_inner() + retry(sdk.address_list(), retry_settings, fut) + .await + .into_inner() } /// Fetch single object from Platform. @@ -222,7 +254,7 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [Error] instances. - async fn fetch_with_settings::Request>>( + async fn fetch_with_settings::Query>>( sdk: &Sdk, query: Q, settings: RequestSettings, @@ -243,121 +275,149 @@ where /// - `id`: An [Identifier] of the object to be fetched. async fn fetch_by_identifier(sdk: &Sdk, id: Identifier) -> Result, Error> where - Identifier: Query<::Request>, + Identifier: Query<::Query>, { Self::fetch(sdk, id).await } } impl Fetch for Identity { + type Query = IdentityRequest; type Request = IdentityRequest; } impl Fetch for dpp::prelude::DataContract { + type Query = platform_proto::GetDataContractRequest; type Request = platform_proto::GetDataContractRequest; } impl Fetch for (dpp::prelude::DataContract, Vec) { + type Query = platform_proto::GetDataContractRequest; type Request = platform_proto::GetDataContractRequest; } impl Fetch for Document { - type Request = DocumentQuery; + type Query = DocumentQuery; + type Request = platform_proto::GetDocumentsRequest; } impl Fetch for drive_proof_verifier::types::IdentityBalance { + type Query = platform_proto::GetIdentityBalanceRequest; type Request = platform_proto::GetIdentityBalanceRequest; } impl Fetch for drive_proof_verifier::types::AddressInfo { + type Query = platform_proto::GetAddressInfoRequest; type Request = platform_proto::GetAddressInfoRequest; } impl Fetch for drive_proof_verifier::types::TotalCreditsInPlatform { + type Query = platform_proto::GetTotalCreditsInPlatformRequest; type Request = platform_proto::GetTotalCreditsInPlatformRequest; } impl Fetch for drive_proof_verifier::types::IdentityNonceFetcher { + type Query = platform_proto::GetIdentityNonceRequest; type Request = platform_proto::GetIdentityNonceRequest; } impl Fetch for drive_proof_verifier::types::IdentityContractNonceFetcher { + type Query = platform_proto::GetIdentityContractNonceRequest; type Request = platform_proto::GetIdentityContractNonceRequest; } impl Fetch for drive_proof_verifier::types::IdentityBalanceAndRevision { + type Query = platform_proto::GetIdentityBalanceAndRevisionRequest; type Request = platform_proto::GetIdentityBalanceAndRevisionRequest; } impl Fetch for drive_proof_verifier::types::DataContractHistory { + type Query = platform_proto::GetDataContractHistoryRequest; type Request = platform_proto::GetDataContractHistoryRequest; } impl Fetch for ExtendedEpochInfo { + type Query = platform_proto::GetEpochsInfoRequest; type Request = platform_proto::GetEpochsInfoRequest; } impl Fetch for drive_proof_verifier::types::PrefundedSpecializedBalance { + type Query = platform_proto::GetPrefundedSpecializedBalanceRequest; type Request = platform_proto::GetPrefundedSpecializedBalanceRequest; } impl Fetch for Vote { + type Query = platform_proto::GetContestedResourceIdentityVotesRequest; type Request = platform_proto::GetContestedResourceIdentityVotesRequest; } impl Fetch for RewardDistributionMoment { + type Query = platform_proto::GetTokenPerpetualDistributionLastClaimRequest; type Request = platform_proto::GetTokenPerpetualDistributionLastClaimRequest; } /// Fetch contract-scoped keys for multiple identities. impl Fetch for IdentitiesContractKeys { + type Query = platform_proto::GetIdentitiesContractKeysRequest; type Request = platform_proto::GetIdentitiesContractKeysRequest; } impl Fetch for dpp::tokens::contract_info::TokenContractInfo { + type Query = platform_proto::GetTokenContractInfoRequest; type Request = platform_proto::GetTokenContractInfoRequest; } impl Fetch for drive_proof_verifier::types::RecentAddressBalanceChanges { + type Query = platform_proto::GetRecentAddressBalanceChangesRequest; type Request = platform_proto::GetRecentAddressBalanceChangesRequest; } impl Fetch for drive_proof_verifier::types::RecentCompactedAddressBalanceChanges { + type Query = platform_proto::GetRecentCompactedAddressBalanceChangesRequest; type Request = platform_proto::GetRecentCompactedAddressBalanceChangesRequest; } impl Fetch for drive_proof_verifier::types::PlatformAddressTrunkState { + type Query = platform_proto::GetAddressesTrunkStateRequest; type Request = platform_proto::GetAddressesTrunkStateRequest; } impl Fetch for drive_proof_verifier::types::ShieldedPoolState { + type Query = platform_proto::GetShieldedPoolStateRequest; type Request = platform_proto::GetShieldedPoolStateRequest; } impl Fetch for drive_proof_verifier::types::ShieldedAnchors { + type Query = platform_proto::GetShieldedAnchorsRequest; type Request = platform_proto::GetShieldedAnchorsRequest; } impl Fetch for drive_proof_verifier::types::MostRecentShieldedAnchor { + type Query = platform_proto::GetMostRecentShieldedAnchorRequest; type Request = platform_proto::GetMostRecentShieldedAnchorRequest; } impl Fetch for drive_proof_verifier::types::ShieldedEncryptedNotes { + type Query = platform_proto::GetShieldedEncryptedNotesRequest; type Request = platform_proto::GetShieldedEncryptedNotesRequest; } impl Fetch for drive_proof_verifier::types::ShieldedNullifierStatuses { + type Query = platform_proto::GetShieldedNullifiersRequest; type Request = platform_proto::GetShieldedNullifiersRequest; } impl Fetch for drive_proof_verifier::types::NullifiersTrunkState { + type Query = platform_proto::GetNullifiersTrunkStateRequest; type Request = platform_proto::GetNullifiersTrunkStateRequest; } impl Fetch for drive_proof_verifier::types::RecentNullifierChanges { + type Query = platform_proto::GetRecentNullifierChangesRequest; type Request = platform_proto::GetRecentNullifierChangesRequest; } impl Fetch for drive_proof_verifier::types::RecentCompactedNullifierChanges { + type Query = platform_proto::GetRecentCompactedNullifierChangesRequest; type Request = platform_proto::GetRecentCompactedNullifierChangesRequest; } diff --git a/packages/rs-sdk/src/platform/fetch_many.rs b/packages/rs-sdk/src/platform/fetch_many.rs index e19a256ffb1..c2bd33bd19e 100644 --- a/packages/rs-sdk/src/platform/fetch_many.rs +++ b/packages/rs-sdk/src/platform/fetch_many.rs @@ -89,19 +89,30 @@ where Self: Sized, O: MockResponse + FromProof< - Self::Request, - Request = Self::Request, + Self::Query, + Request = Self::Query, Response = <>::Request as TransportRequest>::Response, > + Send + Default, { - /// Type of request used to fetch multiple objects from Platform. - /// - /// Most likely, one of the types defined in [`dapi_grpc::platform::v0`]. - /// - /// This type must implement [`TransportRequest`]. - type Request: TransportRequest - + Into<>::Request>>::Request>; + /// User-facing query type — the rich form that callers hand to the + /// SDK and that [`FromProof`] binds to. See [`super::Fetch::Query`] + /// for the rationale; the split lets [`Self::Request`] be the + /// protocol-version-aware wire encoding while keeping the proof + /// verifier surface PV-agnostic. + // + // Associated-type defaults are nightly-only (RFC 2532); each impl + // must spell out `type Query = Self::Request;` when the rich and + // wire forms coincide. + type Query: Query<>::Request> + + dapi_grpc::mock::Mockable + + Clone + + std::fmt::Debug + + Send + + Sync; + + /// Wire-encoded request that hits the network. + type Request: TransportRequest; /// Fetch (or search) multiple objects on the Dash Platform /// @@ -141,7 +152,7 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [`Error`](crate::error::Error) instances. - async fn fetch_many>::Request>>( + async fn fetch_many>::Query>>( sdk: &Sdk, query: Q, ) -> Result { @@ -171,7 +182,7 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [Error] instances. - async fn fetch_many_with_metadata>::Request>>( + async fn fetch_many_with_metadata>::Query>>( sdk: &Sdk, query: Q, settings: Option, @@ -202,19 +213,23 @@ where /// ## Error Handling /// /// Any errors encountered during the execution are returned as [Error] instances. - async fn fetch_many_with_metadata_and_proof>::Request>>( + async fn fetch_many_with_metadata_and_proof>::Query>>( sdk: &Sdk, query: Q, - settings: Option, + request_settings: Option, ) -> Result<(O, ResponseMetadata, Proof), Error> { - let request = &query.query(sdk.prove())?; + let settings = sdk.query_settings(); + let owned_rich: >::Query = query.query(&settings)?; + let owned_wire: >::Request = owned_rich.query(&settings)?; + let rich = &owned_rich; + let wire = &owned_wire; let fut = |settings: RequestSettings| async move { let ExecutionResponse { address, retries, inner: response, - } = request + } = wire .clone() .execute(sdk, settings) .await @@ -222,7 +237,7 @@ where let object_type = std::any::type_name::().to_string(); tracing::trace!( - request = ?request, + request = ?wire, response = ?response, ?address, retries, @@ -230,9 +245,10 @@ where "fetched objects from platform" ); - sdk.parse_proof_with_metadata_and_proof::<>::Request, O>( - request.clone(), + sdk.parse_proof_with_metadata_and_proof::<>::Query, O>( + rich.clone(), response, + wire.method_name(), ) .await .map_err(|e| ExecutionError { @@ -247,11 +263,13 @@ where }) }; - let settings = sdk + let retry_settings = sdk .dapi_client_settings - .override_by(settings.unwrap_or_default()); + .override_by(request_settings.unwrap_or_default()); - retry(sdk.address_list(), settings, fut).await.into_inner() + retry(sdk.address_list(), retry_settings, fut) + .await + .into_inner() } /// Fetch multiple objects from Platform by their identifiers. @@ -272,7 +290,7 @@ where identifiers: I, ) -> Result where - Vec: Query<>::Request>, + Vec: Query<>::Query>, { let ids = identifiers.into_iter().collect::>(); Self::fetch_many(sdk, ids).await @@ -288,13 +306,13 @@ where /// - `sdk`: An instance of [Sdk]. /// - `query`: A query parameter implementing [`Query`](crate::platform::query::Query) to specify the data to be retrieved. /// - `limit`: Maximum number of objects to fetch. - async fn fetch_many_with_limit>::Request>>( + async fn fetch_many_with_limit>::Query>>( sdk: &Sdk, query: Q, limit: u32, ) -> Result where - LimitQuery: Query<>::Request>, + LimitQuery: Query<>::Query>, { let limit_query = LimitQuery { limit: Some(limit), @@ -318,7 +336,8 @@ impl FetchMany for Document { // We need to use the DocumentQuery type here because the DocumentQuery // type stores full contract, which is missing in the GetDocumentsRequest type. // TODO: Refactor to use ContextProvider - type Request = DocumentQuery; + type Query = DocumentQuery; + type Request = dapi_grpc::platform::v0::GetDocumentsRequest; } /// Retrieve public keys for a given identity. @@ -330,6 +349,7 @@ impl FetchMany for Document { /// /// * [Identifier] - [Identity](crate::platform::Identity) ID for which to retrieve keys impl FetchMany for IdentityPublicKey { + type Query = GetIdentityKeysRequest; type Request = GetIdentityKeysRequest; } @@ -345,6 +365,7 @@ impl FetchMany for IdentityPublicKey { /// * [`LimitQuery`](super::LimitQuery), [`LimitQuery`](super::LimitQuery) - limit query /// that allows to specify maximum number of objects to fetch; see also [FetchMany::fetch_many_with_limit()]. impl FetchMany for ExtendedEpochInfo { + type Query = GetEpochsInfoRequest; type Request = GetEpochsInfoRequest; } @@ -358,6 +379,7 @@ impl FetchMany for ExtendedEpochInfo { /// * [`(EpochIndex, EpochIndex)`] - tuple of (start_epoch, end_epoch) indices /// * [`LimitQuery`](super::LimitQuery) - limit query that allows to specify maximum number of objects to fetch impl FetchMany for FinalizedEpochInfo { + type Query = GetFinalizedEpochInfosRequest; type Request = GetFinalizedEpochInfosRequest; } @@ -382,6 +404,7 @@ impl FetchMany for FinalizedEpochInfo { /// # }); /// ``` impl FetchMany for ProtocolVersionVoteCount { + type Query = GetProtocolVersionUpgradeStateRequest; type Request = GetProtocolVersionUpgradeStateRequest; } @@ -400,6 +423,7 @@ impl FetchMany for ProtocolVersionVote /// * [`LimitQuery`](super::LimitQuery) - limit query that allows to specify maximum number of objects /// to fetch; see also [FetchMany::fetch_many_with_limit()]. impl FetchMany for MasternodeProtocolVote { + type Query = GetProtocolVersionUpgradeVoteStatusRequest; type Request = GetProtocolVersionUpgradeVoteStatusRequest; } @@ -416,6 +440,7 @@ impl FetchMany for MasternodeProtocolVote { /// * [`LimitQuery`](super::LimitQuery) - limit query wrapping /// a raw request for more fine-grained control impl FetchMany for ProposerBlockCountByRange { + type Query = GetEvonodesProposedEpochBlocksByRangeRequest; type Request = GetEvonodesProposedEpochBlocksByRangeRequest; } @@ -431,6 +456,7 @@ impl FetchMany for ProposerBlockCountByRange { /// and a list of evonode ProTxHashes to look up /// * [`(EpochIndex, Vec)`] - tuple of epoch index and list of evonode ProTxHashes impl FetchMany for ProposerBlockCountById { + type Query = GetEvonodesProposedEpochBlocksByIdsRequest; type Request = GetEvonodesProposedEpochBlocksByIdsRequest; } @@ -443,6 +469,7 @@ impl FetchMany for ProposerBlockCountById { /// * `Vec` - list of identifiers of data contracts to fetch /// impl FetchMany for DataContract { + type Query = GetDataContractsRequest; type Request = GetDataContractsRequest; } @@ -452,6 +479,7 @@ impl FetchMany for DataContract { /// /// * [`VotePollsByDocumentTypeQuery`](drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery) impl FetchMany for ContestedResource { + type Query = GetContestedResourcesRequest; type Request = GetContestedResourcesRequest; } @@ -464,6 +492,7 @@ impl FetchMany for ContestedResource { /// * [`ContestedDocumentVotePollDriveQuery`](drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQuery) #[async_trait::async_trait] impl FetchMany for ContenderWithSerializedDocument { + type Query = GetContestedResourceVoteStateRequest; type Request = GetContestedResourceVoteStateRequest; } @@ -473,6 +502,7 @@ impl FetchMany for ContenderWithSerializedDocument { /// /// * [`ContestedDocumentVotePollVotesDriveQuery`](drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery) impl FetchMany for Voter { + type Query = GetContestedResourceVotersForIdentityRequest; type Request = GetContestedResourceVotersForIdentityRequest; } @@ -483,6 +513,7 @@ impl FetchMany for Voter { /// /// * [`ContestedResourceVotesGivenByIdentityQuery`](drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery) impl FetchMany for ResourceVote { + type Query = GetContestedResourceIdentityVotesRequest; type Request = GetContestedResourceIdentityVotesRequest; } @@ -493,6 +524,7 @@ impl FetchMany for ResourceVote { /// /// * [`VotePollsByEndDateDriveQuery`](drive::query::VotePollsByEndDateDriveQuery) impl FetchMany for VotePoll { + type Query = GetVotePollsByEndDateRequest; type Request = GetVotePollsByEndDateRequest; } @@ -503,10 +535,12 @@ impl FetchMany for VotePoll { /// /// * `Vec` - list of identifiers of identities whose balance we want to fetch impl FetchMany for drive_proof_verifier::types::IdentityBalance { + type Query = GetIdentitiesBalancesRequest; type Request = GetIdentitiesBalancesRequest; } impl FetchMany for drive_proof_verifier::types::AddressInfo { + type Query = GetAddressesInfosRequest; type Request = GetAddressesInfosRequest; } @@ -517,6 +551,7 @@ impl FetchMany for drive_proof_verifier::types::A /// /// * [`KeysInPath`](drive_proof_verifier::types::KeysInPath) impl FetchMany for Element { + type Query = GetPathElementsRequest; type Request = GetPathElementsRequest; } @@ -526,5 +561,6 @@ impl FetchMany for Element { /// /// * [`&\[Identifier\]`](dpp::prelude::Identifier) - list of identifiers of tokens whose prices we want to fetch impl FetchMany for TokenPricingSchedule { + type Query = GetTokenDirectPurchasePricesRequest; type Request = GetTokenDirectPurchasePricesRequest; } diff --git a/packages/rs-sdk/src/platform/fetch_unproved.rs b/packages/rs-sdk/src/platform/fetch_unproved.rs index b368f87d3a3..f9a8bb30064 100644 --- a/packages/rs-sdk/src/platform/fetch_unproved.rs +++ b/packages/rs-sdk/src/platform/fetch_unproved.rs @@ -61,7 +61,7 @@ where async fn fetch_unproved_with_settings::Request>>( sdk: &Sdk, query: Q, - settings: RequestSettings, + request_settings: RequestSettings, ) -> Result<(Option, ResponseMetadata), Error> where Self: FromUnproved< @@ -71,7 +71,8 @@ where >, { // Default implementation - let request: &::Request = &query.query(false)?; + let settings = sdk.query_settings().without_proofs(); + let request: &::Request = &query.query(&settings)?; let closure = move |local_settings: RequestSettings| async move { // Execute the request using the Sdk instance let ExecutionResponse { @@ -105,8 +106,8 @@ where }) }; - let settings = sdk.dapi_client_settings.override_by(settings); - retry(sdk.address_list(), settings, closure) + let retry_settings = sdk.dapi_client_settings.override_by(request_settings); + retry(sdk.address_list(), retry_settings, closure) .await .into_inner() } diff --git a/packages/rs-sdk/src/platform/group_actions.rs b/packages/rs-sdk/src/platform/group_actions.rs index c12199ae04d..6375119b9a9 100644 --- a/packages/rs-sdk/src/platform/group_actions.rs +++ b/packages/rs-sdk/src/platform/group_actions.rs @@ -30,7 +30,11 @@ pub struct GroupQuery { } impl Query for GroupQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetGroupInfoRequest { version: Some(get_group_info_request::Version::V0(GetGroupInfoRequestV0 { contract_id: self.contract_id.to_vec(), @@ -44,6 +48,7 @@ impl Query for GroupQuery { } impl Fetch for Group { + type Query = GetGroupInfoRequest; type Request = GetGroupInfoRequest; } @@ -61,7 +66,11 @@ pub struct GroupInfosQuery { } impl Query for GroupInfosQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetGroupInfosRequest { version: Some(get_group_infos_request::Version::V0( GetGroupInfosRequestV0 { @@ -83,6 +92,7 @@ impl Query for GroupInfosQuery { } impl FetchMany for Group { + type Query = GetGroupInfosRequest; type Request = GetGroupInfosRequest; } @@ -104,7 +114,11 @@ pub struct GroupActionsQuery { } impl Query for GroupActionsQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetGroupActionsRequest { version: Some(get_group_actions_request::Version::V0( GetGroupActionsRequestV0 { @@ -128,6 +142,7 @@ impl Query for GroupActionsQuery { } impl FetchMany for GroupAction { + type Query = GetGroupActionsRequest; type Request = GetGroupActionsRequest; } @@ -145,7 +160,11 @@ pub struct GroupActionSignersQuery { } impl Query for GroupActionSignersQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetGroupActionSignersRequest { version: Some(get_group_action_signers_request::Version::V0( GetGroupActionSignersRequestV0 { @@ -163,5 +182,6 @@ impl Query for GroupActionSignersQuery { } impl FetchMany for GroupMemberPower { + type Query = GetGroupActionSignersRequest; type Request = GetGroupActionSignersRequest; } diff --git a/packages/rs-sdk/src/platform/identities_contract_keys_query.rs b/packages/rs-sdk/src/platform/identities_contract_keys_query.rs index c026b4a9de2..02ede03136f 100644 --- a/packages/rs-sdk/src/platform/identities_contract_keys_query.rs +++ b/packages/rs-sdk/src/platform/identities_contract_keys_query.rs @@ -65,7 +65,11 @@ impl TryFrom for GetIdentitiesContractKeysRequest { } impl Query for IdentitiesContractKeysQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let IdentitiesContractKeysQuery { identities_ids, contract_id, @@ -74,10 +78,10 @@ impl Query for IdentitiesContractKeysQuery { } = self; Ok(GetIdentitiesContractKeysRequest { version: Some(V0(GetIdentitiesContractKeysRequestV0 { - identities_ids: identities_ids.into_iter().map(|a| a.to_vec()).collect(), + identities_ids: identities_ids.iter().map(|a| a.to_vec()).collect(), contract_id: contract_id.to_vec(), - document_type_name, - purposes: purposes.into_iter().map(|purpose| purpose as i32).collect(), + document_type_name: document_type_name.clone(), + purposes: purposes.iter().map(|purpose| *purpose as i32).collect(), prove, })), }) diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index 043cb5941b8..3a99993e111 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -92,23 +92,22 @@ pub const DEFAULT_NODES_VOTING_LIMIT: u32 = 100; /// As [`Identifier`] implements [Query], the `query` variable in the code /// above can be used as a parameter for [Fetch::fetch()](crate::platform::Fetch::fetch()) /// and [FetchMany::fetch_many()](crate::platform::FetchMany::fetch_many()) methods. -pub trait Query: Send + Debug + Clone { - /// Converts the current instance into an instance of the `TransportRequest` type. - /// - /// This method takes ownership of the instance upon which it's called (hence `self`), and attempts to perform the conversion. +pub trait Query: Send + Debug + Clone { + /// Convert the query into a wire-shape [`TransportRequest`]. /// /// # Arguments /// - /// * `prove` - Whether to include proofs in the response. Only `true` is supported at the moment. + /// * `settings` - A [`QuerySettings`](crate::platform::QuerySettings) borrowing the encoder + /// inputs from the SDK: protocol version (used by encoders that pick wire shapes + /// per version — today only [`DocumentQuery`]'s V0/V1 split), `prove` flag, + /// and request settings. Construct from an SDK via + /// [`Sdk::query_settings`](crate::Sdk::query_settings), or directly in unit tests + /// that want to exercise the encoder without spinning up an `Sdk`. /// /// # Returns /// On success, this method yields an instance of the `TransportRequest` type (`T`). /// On failure, it yields an [`Error`]. - /// - /// # Error Handling - /// This method propagates any errors encountered during the conversion process. - /// These are returned as [`Error`] instances. - fn query(self, prove: bool) -> Result; + fn query(&self, settings: &crate::platform::QuerySettings<'_>) -> Result; } impl Query for T @@ -116,16 +115,21 @@ where T: TransportRequest + Sized + Send + Sync + Clone + Debug, T::Response: Send + Sync + Debug, { - fn query(self, prove: bool) -> Result { + fn query(&self, settings: &crate::platform::QuerySettings<'_>) -> Result { + let prove = settings.prove; if !prove { tracing::warn!(request= ?self, "sending query without proof, ensure data is trusted"); } - Ok(self) + Ok(self.clone()) } } impl Query for Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -139,11 +143,15 @@ impl Query for Identifier { } impl Query for Vec { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - let ids = self.into_iter().map(|id| id.to_vec()).collect(); + let ids = self.iter().map(|id| id.to_vec()).collect(); Ok(proto::GetDataContractsRequest { version: Some(proto::get_data_contracts_request::Version::V0( proto::get_data_contracts_request::GetDataContractsRequestV0 { ids, prove }, @@ -153,7 +161,11 @@ impl Query for Vec { } impl Query for LimitQuery<(Identifier, u64)> { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -175,7 +187,11 @@ impl Query for LimitQuery<(Identifier, u64 impl Query for Identifier { /// Get all keys for an identity with provided identifier. - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -250,7 +266,11 @@ impl IdentityKeysQuery { impl Query for IdentityKeysQuery { /// Get specific keys for an identity. - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -265,7 +285,7 @@ impl Query for IdentityKeysQuery { request_type: Some(KeyRequestType { request: Some(proto::key_request_type::Request::SpecificKeys( SpecificKeys { - key_ids: self.key_ids.into_iter().collect(), + key_ids: self.key_ids.to_vec(), }, )), }), @@ -276,7 +296,11 @@ impl Query for IdentityKeysQuery { } impl Query for PlatformAddress { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -293,12 +317,16 @@ impl Query for PlatformAddress { } impl Query for BTreeSet { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - let addresses = self.into_iter().map(|address| address.to_bytes()).collect(); + let addresses = self.iter().map(|address| address.to_bytes()).collect(); Ok(GetAddressesInfosRequest { version: Some(get_addresses_infos_request::Version::V0( @@ -309,7 +337,11 @@ impl Query for BTreeSet { } impl Query for () { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -323,7 +355,8 @@ impl Query for () { } impl Query for DriveDocumentQuery<'_> { - fn query(self, prove: bool) -> Result { + fn query(&self, settings: &crate::platform::QuerySettings<'_>) -> Result { + let prove = settings.prove; if !prove { // dash-sdk only serves proof-verified responses. Raw, // unverified gRPC responses are out of scope for the @@ -335,11 +368,26 @@ impl Query for DriveDocumentQuery<'_> { .to_string(), )); } - let q: DocumentQuery = (&self).into(); + let q: DocumentQuery = self.into(); Ok(q) } } +// `DocumentQuery` does not implement [`TransportRequest`] (the wire form is +// [`GetDocumentsRequest`]), so the blanket `Query for T` does not apply +// to it. Provide the identity impl explicitly so the SDK fetch trampoline +// can use a [`DocumentQuery`] both as the user-supplied `Q` and as the +// rich `Self::Query` produced by `Q::query(sdk)`. +impl Query for DocumentQuery { + fn query(&self, settings: &crate::platform::QuerySettings<'_>) -> Result { + let prove = settings.prove; + if !prove { + tracing::warn!(request= ?self, "sending query without proof, ensure data is trusted"); + } + Ok(self.clone()) + } +} + #[derive(Debug, Clone)] pub struct QueryStartInfo { pub start_key: Vec, @@ -388,11 +436,15 @@ impl From for LimitQuery { } impl + Clone + Debug + Send> Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - let inner: EpochQuery = self.query.into(); + let inner: EpochQuery = self.query.clone().into(); Ok(GetEpochsInfoRequest { version: Some(proto::get_epochs_info_request::Version::V0( proto::get_epochs_info_request::GetEpochsInfoRequestV0 { @@ -407,18 +459,25 @@ impl + Clone + Debug + Send> Query for } impl Query for EpochIndex { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { LimitQuery { - query: self, + query: *self, start_info: None, limit: Some(1), } - .query(prove) + .query(settings) } } impl Query for () { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -428,7 +487,11 @@ impl Query for () { } impl Query for LimitQuery> { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -436,7 +499,7 @@ impl Query for LimitQuery for LimitQuery for Option { - fn query(self, prove: bool) -> Result { - LimitQuery::from(self).query(prove) + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + LimitQuery::from(*self).query(settings) } } /// Convenience method that allows direct use of a ProTxHash impl Query for ProTxHash { - fn query(self, prove: bool) -> Result { - Some(self).query(prove) + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + Some(*self).query(settings) } } /// Convenience method that allows direct use of a ProTxHash impl Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { LimitQuery { query: Some(self.query), start_info: None, limit: self.limit, } - .query(prove) + .query(settings) } } impl Query for VotePollsByDocumentTypeQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - self.try_to_request().map_err(|e| e.into()) + self.clone().try_to_request().map_err(|e| e.into()) } } impl Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { use proto::get_contested_resources_request::{ get_contested_resources_request_v0::StartAtValueInfo, Version, }; - let query = match self.query.query(prove)?.version { + let query = match self.query.query(settings)?.version { Some(Version::V0(v0)) => GetContestedResourcesRequestV0 { - start_at_value_info: self.start_info.map(|v| StartAtValueInfo { + start_at_value_info: self.start_info.clone().map(|v| StartAtValueInfo { start_value: v.start_key, start_value_included: v.start_included, }), @@ -508,7 +587,11 @@ impl Query for LimitQuery for ContestedDocumentVotePollDriveQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -516,22 +599,26 @@ impl Query for ContestedDocumentVotePollDr if self.offset.is_some() { return Err(Error::Generic("ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None".into())); } - self.try_to_request().map_err(|e| e.into()) + self.clone().try_to_request().map_err(|e| e.into()) } } impl Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; use proto::get_contested_resource_vote_state_request::get_contested_resource_vote_state_request_v0::StartAtIdentifierInfo; if !prove { unimplemented!("queries without proofs are not supported yet"); } - let result = match self.query.query(prove)?.version { + let result = match self.query.query(settings)?.version { Some(proto::get_contested_resource_vote_state_request::Version::V0(v0)) => proto::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0 { - start_at_identifier_info: self.start_info.map(|v| StartAtIdentifierInfo { + start_at_identifier_info: self.start_info.clone().map(|v| StartAtIdentifierInfo { start_identifier: v.start_key, start_identifier_included: v.start_included, }), @@ -550,7 +637,11 @@ impl Query impl Query for ContestedDocumentVotePollVotesDriveQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -558,20 +649,23 @@ impl Query return Err(Error::Generic("ContestedDocumentVotePollVotesDriveQuery.offset field is internal and must be set to None".into())); } - self.try_to_request().map_err(|e| e.into()) + self.clone().try_to_request().map_err(|e| e.into()) } } impl Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { use proto::get_contested_resource_voters_for_identity_request::{ get_contested_resource_voters_for_identity_request_v0::StartAtIdentifierInfo, Version, }; - let query = match self.query.query(prove)?.version { + let query = match self.query.query(settings)?.version { Some(Version::V0(v0)) => GetContestedResourceVotersForIdentityRequestV0 { - start_at_identifier_info: self.start_info.map(|v| StartAtIdentifierInfo { + start_at_identifier_info: self.start_info.clone().map(|v| StartAtIdentifierInfo { start_identifier: v.start_key, start_identifier_included: v.start_included, }), @@ -595,13 +689,16 @@ impl Query impl Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { use proto::get_evonodes_proposed_epoch_blocks_by_range_request::{ get_evonodes_proposed_epoch_blocks_by_range_request_v0::Start, Version, }; - let query = match self.query.query(prove)?.version { + let query = match self.query.query(settings)?.version { Some(Version::V0(v0)) => GetEvonodesProposedEpochBlocksByRangeRequestV0 { - start: self.start_info.map(|v| { + start: self.start_info.clone().map(|v| { if v.start_included { Start::StartAt(v.start_key) } else { @@ -628,7 +725,11 @@ impl Query impl Query for ContestedResourceVotesGivenByIdentityQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -636,12 +737,16 @@ impl Query return Err(Error::Generic("ContestedResourceVotesGivenByIdentityQuery.offset field is internal and must be set to None".into())); } - self.try_to_request().map_err(|e| e.into()) + self.clone().try_to_request().map_err(|e| e.into()) } } impl Query for ProTxHash { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -658,21 +763,29 @@ impl Query for ProTxHash { } impl Query for VotePollsByEndDateDriveQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - self.try_to_request().map_err(|e| e.into()) + self.clone().try_to_request().map_err(|e| e.into()) } } impl Query for Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - self.try_to_request().map_err(|e| e.into()) + self.clone().try_to_request().map_err(|e| e.into()) } } @@ -692,7 +805,11 @@ impl VoteQuery { } impl Query for VoteQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -714,7 +831,11 @@ impl Query for VoteQuery { } impl Query for LimitQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -722,13 +843,15 @@ impl Query for LimitQuery { get_contested_resource_identity_votes_request_v0::StartAtVotePollIdInfo, Version, }; - Ok(match self.query.query(prove)?.version { + Ok(match self.query.query(settings)?.version { None => return Err(Error::Protocol(dpp::ProtocolError::NoProtocolVersionError)), Some(Version::V0(v0)) => GetContestedResourceIdentityVotesRequestV0 { limit: self.limit, - start_at_vote_poll_id_info: self.start_info.map(|v| StartAtVotePollIdInfo { - start_at_poll_identifier: v.start_key.to_vec(), - start_poll_identifier_included: v.start_included, + start_at_vote_poll_id_info: self.start_info.clone().map(|v| { + StartAtVotePollIdInfo { + start_at_poll_identifier: v.start_key.to_vec(), + start_poll_identifier_included: v.start_included, + } }), ..v0 }, @@ -738,7 +861,11 @@ impl Query for LimitQuery { } impl Query for KeysInPath { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -746,8 +873,8 @@ impl Query for KeysInPath { let request: GetPathElementsRequest = GetPathElementsRequest { version: Some(get_path_elements_request::Version::V0( GetPathElementsRequestV0 { - path: self.path, - keys: self.keys, + path: self.path.clone(), + keys: self.keys.clone(), prove, }, )), @@ -758,7 +885,11 @@ impl Query for KeysInPath { } impl Query for NoParamQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -774,7 +905,11 @@ impl Query for NoParamQuery { } impl Query for NoParamQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if prove { unimplemented!( "query with proof are not supported yet for GetCurrentQuorumsInfoRequest" @@ -792,7 +927,11 @@ impl Query for NoParamQuery { } impl Query for LimitQuery> { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -801,7 +940,7 @@ impl Query for LimitQuery for LimitQuery for EvoNode { - fn query(self, _prove: bool) -> Result { + fn query(&self, _ctx: &crate::platform::QuerySettings<'_>) -> Result { // ignore proof let request: GetStatusRequest = GetStatusRequest { @@ -830,7 +969,11 @@ impl Query for EvoNode { } impl Query for &[Identifier] { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -858,7 +1001,11 @@ pub struct TokenLastClaimQuery { } impl Query for TokenLastClaimQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -890,7 +1037,11 @@ pub struct ProposerBlockCountByIdsQuery { } impl Query for ProposerBlockCountByIdsQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -898,7 +1049,7 @@ impl Query for ProposerBlockCountByI // Convert ProTxHash to bytes let ids: Vec> = self .pro_tx_hashes - .into_iter() + .iter() .map(|hash| hash.to_byte_array().to_vec()) .collect(); @@ -918,13 +1069,16 @@ impl Query for ProposerBlockCountByI // Convenience implementation for tuple of (epoch, Vec) impl Query for (EpochIndex, Vec) { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { let (epoch, pro_tx_hashes) = self; ProposerBlockCountByIdsQuery { - epoch: Some(epoch), - pro_tx_hashes, + epoch: Some(*epoch), + pro_tx_hashes: pro_tx_hashes.clone(), } - .query(prove) + .query(settings) } } @@ -943,7 +1097,11 @@ impl RecentAddressBalanceChangesQuery { } impl Query for RecentAddressBalanceChangesQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -980,9 +1138,10 @@ impl Query for RecentCompactedAddressBalanceChangesQuery { fn query( - self, - prove: bool, + &self, + settings: &crate::platform::QuerySettings<'_>, ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -1003,7 +1162,11 @@ impl Query // --- Shielded Pool Queries --- impl Query for NoParamQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -1017,7 +1180,11 @@ impl Query for NoParamQuery { } impl Query for NoParamQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -1031,7 +1198,11 @@ impl Query for NoParamQuery { } impl Query for NoParamQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -1047,7 +1218,11 @@ impl Query for NoParamQuery { } impl Query for ShieldedEncryptedNotesQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -1065,7 +1240,11 @@ impl Query for ShieldedEncryptedNotesQuery { } impl Query for ShieldedNullifiersQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -1073,7 +1252,7 @@ impl Query for ShieldedNullifiersQuery { Ok(GetShieldedNullifiersRequest { version: Some(get_shielded_nullifiers_request::Version::V0( get_shielded_nullifiers_request::GetShieldedNullifiersRequestV0 { - nullifiers: self.0.into_iter().map(|n| n.to_vec()).collect(), + nullifiers: self.0.iter().map(|n| n.to_vec()).collect(), prove, }, )), @@ -1082,7 +1261,11 @@ impl Query for ShieldedNullifiersQuery { } impl Query for NullifiersTrunkQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } diff --git a/packages/rs-sdk/src/platform/query_settings.rs b/packages/rs-sdk/src/platform/query_settings.rs new file mode 100644 index 00000000000..f5741dbe04a --- /dev/null +++ b/packages/rs-sdk/src/platform/query_settings.rs @@ -0,0 +1,48 @@ +//! Query encoding settings. +//! +//! [`QuerySettings`] is a small, borrow-style bundle handed to +//! [`crate::platform::query::Query::query`] implementations so they can encode +//! a user-facing query into a wire `TransportRequest` without taking a full +//! `&Sdk` dependency. This keeps the encoder layer free of `Sdk`-shaped +//! transitive deps (transport, mock cache, nonce cache, context provider, …) +//! and lets unit tests construct settings directly without spinning up +//! `Sdk::new_mock()`. +//! +//! The fields are the minimum surface a wire encoder needs today: +//! protocol version (to pick V0 vs V1 wire shapes), the `prove` flag +//! (proof-mode requests vs unproved queries), and a borrowed +//! [`RequestSettings`] for any future encoder that needs to consult +//! transport-layer hints (timeouts, ban policy, …) — none do today, but +//! it costs nothing to thread through and avoids another trait churn +//! when the first encoder needs it. + +use dpp::version::PlatformVersion; +use rs_dapi_client::RequestSettings; + +/// Settings passed to [`crate::platform::query::Query::query`] for encoding a +/// user-facing query into a wire `TransportRequest`. +/// +/// Construct via [`crate::Sdk::query_settings`] for normal use, or directly in +/// unit tests that want to exercise the encoder without an `Sdk`. +#[derive(Debug, Clone, Copy)] +pub struct QuerySettings<'a> { + /// Transport-layer settings (timeouts, retries, TLS, ban behaviour). + /// Not consulted by any current encoder; threaded for forward compatibility. + pub request_settings: &'a RequestSettings, + + /// Platform protocol version, used to pick wire encoding (V0 vs V1, etc). + pub protocol_version: &'a PlatformVersion, + + /// Whether to request and verify cryptographic proofs. + pub prove: bool, +} + +impl<'a> QuerySettings<'a> { + /// Cheap derivative with proofs forced off — used by `FetchUnproved`. + pub fn without_proofs(&self) -> Self { + Self { + prove: false, + ..*self + } + } +} diff --git a/packages/rs-sdk/src/platform/tokens/identity_token_balances.rs b/packages/rs-sdk/src/platform/tokens/identity_token_balances.rs index bcc3c85dab4..adc0f928ad0 100644 --- a/packages/rs-sdk/src/platform/tokens/identity_token_balances.rs +++ b/packages/rs-sdk/src/platform/tokens/identity_token_balances.rs @@ -21,12 +21,16 @@ pub struct IdentityTokenBalancesQuery { } impl Query for IdentityTokenBalancesQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetIdentityTokenBalancesRequest { version: Some(get_identity_token_balances_request::Version::V0( GetIdentityTokenBalancesRequestV0 { identity_id: self.identity_id.to_vec(), - token_ids: self.token_ids.into_iter().map(|id| id.to_vec()).collect(), + token_ids: self.token_ids.iter().map(|id| id.to_vec()).collect(), prove, }, )), @@ -37,6 +41,7 @@ impl Query for IdentityTokenBalancesQuery { } impl FetchMany for TokenAmount { + type Query = GetIdentityTokenBalancesRequest; type Request = GetIdentityTokenBalancesRequest; } @@ -50,15 +55,15 @@ pub struct IdentitiesTokenBalancesQuery { } impl Query for IdentitiesTokenBalancesQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetIdentitiesTokenBalancesRequest { version: Some(get_identities_token_balances_request::Version::V0( GetIdentitiesTokenBalancesRequestV0 { - identity_ids: self - .identity_ids - .into_iter() - .map(|id| id.to_vec()) - .collect(), + identity_ids: self.identity_ids.iter().map(|id| id.to_vec()).collect(), token_id: self.token_id.to_vec(), prove, }, @@ -70,5 +75,6 @@ impl Query for IdentitiesTokenBalancesQuery { } impl FetchMany for TokenAmount { + type Query = GetIdentitiesTokenBalancesRequest; type Request = GetIdentitiesTokenBalancesRequest; } diff --git a/packages/rs-sdk/src/platform/tokens/token_contract_info.rs b/packages/rs-sdk/src/platform/tokens/token_contract_info.rs index deaae35e8de..879bf41e307 100644 --- a/packages/rs-sdk/src/platform/tokens/token_contract_info.rs +++ b/packages/rs-sdk/src/platform/tokens/token_contract_info.rs @@ -11,7 +11,11 @@ pub struct TokenContractInfoQuery { } impl Query for TokenContractInfoQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetTokenContractInfoRequest { version: Some(get_token_contract_info_request::Version::V0( GetTokenContractInfoRequestV0 { @@ -26,7 +30,10 @@ impl Query for TokenContractInfoQuery { } impl Query for Identifier { - fn query(self, prove: bool) -> Result { - TokenContractInfoQuery { token_id: self }.query(prove) + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + TokenContractInfoQuery { token_id: *self }.query(settings) } } diff --git a/packages/rs-sdk/src/platform/tokens/token_info.rs b/packages/rs-sdk/src/platform/tokens/token_info.rs index 41841e75b17..8039937b5ff 100644 --- a/packages/rs-sdk/src/platform/tokens/token_info.rs +++ b/packages/rs-sdk/src/platform/tokens/token_info.rs @@ -19,12 +19,16 @@ pub struct IdentityTokenInfosQuery { } impl Query for IdentityTokenInfosQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetIdentityTokenInfosRequest { version: Some(get_identity_token_infos_request::Version::V0( GetIdentityTokenInfosRequestV0 { identity_id: self.identity_id.to_vec(), - token_ids: self.token_ids.into_iter().map(|id| id.to_vec()).collect(), + token_ids: self.token_ids.iter().map(|id| id.to_vec()).collect(), prove, }, )), @@ -35,6 +39,7 @@ impl Query for IdentityTokenInfosQuery { } impl FetchMany for IdentityTokenInfo { + type Query = GetIdentityTokenInfosRequest; type Request = GetIdentityTokenInfosRequest; } @@ -48,15 +53,15 @@ pub struct IdentitiesTokenInfosQuery { } impl Query for IdentitiesTokenInfosQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetIdentitiesTokenInfosRequest { version: Some(get_identities_token_infos_request::Version::V0( GetIdentitiesTokenInfosRequestV0 { - identity_ids: self - .identity_ids - .into_iter() - .map(|id| id.to_vec()) - .collect(), + identity_ids: self.identity_ids.iter().map(|id| id.to_vec()).collect(), token_id: self.token_id.to_vec(), prove, }, @@ -70,5 +75,6 @@ impl Query for IdentitiesTokenInfosQuery { // TODO: Implement Fetch (and for others) impl FetchMany for IdentityTokenInfo { + type Query = GetIdentitiesTokenInfosRequest; type Request = GetIdentitiesTokenInfosRequest; } diff --git a/packages/rs-sdk/src/platform/tokens/token_pre_programmed_distributions.rs b/packages/rs-sdk/src/platform/tokens/token_pre_programmed_distributions.rs index e79de6e588b..56cdbfabbb6 100644 --- a/packages/rs-sdk/src/platform/tokens/token_pre_programmed_distributions.rs +++ b/packages/rs-sdk/src/platform/tokens/token_pre_programmed_distributions.rs @@ -32,16 +32,20 @@ pub struct TokenPreProgrammedDistributionsStartAtInfo { } impl Query for TokenPreProgrammedDistributionsQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - let start_at_info = self.start_at_info.map(|info| { + let start_at_info = self.start_at_info.as_ref().map(|info| { let has_recipient = info.start_recipient.is_some(); StartAtInfo { start_time_ms: info.start_time_ms, - start_recipient: info.start_recipient.map(|id| id.to_vec()), + start_recipient: info.start_recipient.as_ref().map(|id| id.to_vec()), // Only set when a start_recipient is provided; meaningless otherwise. start_recipient_included: if has_recipient { Some(info.start_recipient_included) @@ -67,5 +71,6 @@ impl Query for TokenPreProgrammedDist } impl Fetch for TokenPreProgrammedDistributions { + type Query = GetTokenPreProgrammedDistributionsRequest; type Request = GetTokenPreProgrammedDistributionsRequest; } diff --git a/packages/rs-sdk/src/platform/tokens/token_status.rs b/packages/rs-sdk/src/platform/tokens/token_status.rs index 045e0b4f28e..7a801acf840 100644 --- a/packages/rs-sdk/src/platform/tokens/token_status.rs +++ b/packages/rs-sdk/src/platform/tokens/token_status.rs @@ -6,14 +6,15 @@ use dpp::tokens::status::TokenStatus; use drive_proof_verifier::types::token_status::TokenStatuses; impl Query for Vec { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetTokenStatusesRequest { version: Some(get_token_statuses_request::Version::V0( GetTokenStatusesRequestV0 { - token_ids: self - .into_iter() - .map(|identifier| identifier.to_vec()) - .collect(), + token_ids: self.iter().map(|identifier| identifier.to_vec()).collect(), prove, }, )), @@ -24,5 +25,6 @@ impl Query for Vec { } impl FetchMany for TokenStatus { + type Query = GetTokenStatusesRequest; type Request = GetTokenStatusesRequest; } diff --git a/packages/rs-sdk/src/platform/tokens/token_total_supply.rs b/packages/rs-sdk/src/platform/tokens/token_total_supply.rs index 95985243d0b..8cb817c0d1c 100644 --- a/packages/rs-sdk/src/platform/tokens/token_total_supply.rs +++ b/packages/rs-sdk/src/platform/tokens/token_total_supply.rs @@ -5,7 +5,11 @@ use dapi_grpc::platform::v0::{get_token_total_supply_request, GetTokenTotalSuppl pub use dpp::balances::total_single_token_balance::TotalSingleTokenBalance; impl Query for Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; let request = GetTokenTotalSupplyRequest { version: Some(get_token_total_supply_request::Version::V0( GetTokenTotalSupplyRequestV0 { @@ -20,5 +24,6 @@ impl Query for Identifier { } impl Fetch for TotalSingleTokenBalance { + type Query = GetTokenTotalSupplyRequest; type Request = GetTokenTotalSupplyRequest; } diff --git a/packages/rs-sdk/src/platform/types/epoch.rs b/packages/rs-sdk/src/platform/types/epoch.rs index f6b86b77eeb..5983143f72c 100644 --- a/packages/rs-sdk/src/platform/types/epoch.rs +++ b/packages/rs-sdk/src/platform/types/epoch.rs @@ -87,7 +87,10 @@ impl From for EpochQuery { } impl Query for EpochQuery { - fn query(self, prove: bool) -> Result { - LimitQuery::from(self).query(prove) + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + LimitQuery::from(self.clone()).query(settings) } } diff --git a/packages/rs-sdk/src/platform/types/finalized_epoch.rs b/packages/rs-sdk/src/platform/types/finalized_epoch.rs index 74f53b85d70..e9e25f8071d 100644 --- a/packages/rs-sdk/src/platform/types/finalized_epoch.rs +++ b/packages/rs-sdk/src/platform/types/finalized_epoch.rs @@ -40,7 +40,11 @@ impl From<(EpochIndex, EpochIndex)> for FinalizedEpochQuery { } impl Query for FinalizedEpochQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -59,7 +63,10 @@ impl Query for FinalizedEpochQuery { } impl Query for (EpochIndex, EpochIndex) { - fn query(self, prove: bool) -> Result { - FinalizedEpochQuery::from(self).query(prove) + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + FinalizedEpochQuery::from(*self).query(settings) } } diff --git a/packages/rs-sdk/src/platform/types/identity.rs b/packages/rs-sdk/src/platform/types/identity.rs index 963dcaa45f9..a004eb559ff 100644 --- a/packages/rs-sdk/src/platform/types/identity.rs +++ b/packages/rs-sdk/src/platform/types/identity.rs @@ -37,7 +37,11 @@ delegate_enum! { } impl Query for dpp::prelude::Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -59,7 +63,11 @@ impl Query for dpp::prelude::Identifier { pub struct PublicKeyHash(pub [u8; 20]); impl Query for PublicKeyHash { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -84,7 +92,11 @@ pub struct NonUniquePublicKeyHashQuery { } impl Query for NonUniquePublicKeyHashQuery { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -107,7 +119,11 @@ impl Query for NonUniquePublicKeyHashQuery { } impl Query for dpp::prelude::Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -124,7 +140,11 @@ impl Query for dpp::prelude::Identifier { } impl Query for dpp::prelude::Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -145,7 +165,11 @@ impl Query for dpp::prelude::Identifier { impl Query for (dpp::prelude::Identifier, dpp::prelude::Identifier) { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -166,7 +190,11 @@ impl Query } impl Query for dpp::prelude::Identifier { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } @@ -182,11 +210,15 @@ impl Query for dpp::prelude::Identifier { } impl Query for Vec { - fn query(self, prove: bool) -> Result { + fn query( + &self, + settings: &crate::platform::QuerySettings<'_>, + ) -> Result { + let prove = settings.prove; if !prove { unimplemented!("queries without proofs are not supported yet"); } - let ids = self.into_iter().map(|a| a.to_vec()).collect(); + let ids = self.iter().map(|a| a.to_vec()).collect(); let request: GetIdentitiesBalancesRequest = GetIdentitiesBalancesRequest { version: Some(get_identities_balances_request::Version::V0( diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index cad1f5e5103..acc662fb2f0 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -330,9 +330,10 @@ impl Sdk { .fetch_max(received_version, Ordering::Relaxed); if previous < received_version { tracing::info!( - old_version = previous, - new_version = received_version, - "protocol version updated from network metadata" + target: "dash_sdk::protocol_version", + from = previous, + to = received_version, + "ratcheting protocol version upward" ); } } @@ -366,14 +367,14 @@ impl Sdk { &self, request: O::Request, response: O::Response, + method_name: &'static str, ) -> Result<(Option, ResponseMetadata, Proof), Error> where - O::Request: Mockable + TransportRequest, + O::Request: Mockable, { let provider = self .context_provider() .ok_or(drive_proof_verifier::Error::ContextProviderNotSet)?; - let method_name = request.method_name(); let (object, metadata, proof) = match self.inner { SdkInstance::Dapi { .. } => O::maybe_from_proof_with_metadata( @@ -501,6 +502,20 @@ impl Sdk { self.proofs } + /// Build a [`QuerySettings`] borrowing this SDK's protocol version, + /// request settings, and `prove` flag. + /// + /// Hand the resulting context to [`crate::platform::Query::query`] when + /// you need to encode a user-facing query into a wire `TransportRequest` + /// without taking a full `&Sdk` dependency through the encoder layer. + pub fn query_settings(&self) -> crate::platform::QuerySettings<'_> { + crate::platform::QuerySettings { + request_settings: &self.dapi_client_settings, + protocol_version: self.version(), + prove: self.prove(), + } + } + // TODO: If we remove this setter we don't need to use ArcSwap. // It's good enough to set Context once when you initialize the SDK. /// Set the [ContextProvider] to use. @@ -873,6 +888,37 @@ impl SdkBuilder { self } + /// Set the *initial* protocol version seed for auto-detect mode. + /// + /// Unlike [`Self::with_version`], this leaves auto-detect active — + /// the SDK starts at `version.protocol_version` and ratchets upward + /// (via `fetch_max` in `maybe_update_protocol_version`) once the + /// network's actual version is observed in response metadata. + /// + /// Use this when an SDK built against `PlatformVersion::latest()` + /// must talk to a network running an older protocol version (e.g. + /// a v3.0 testnet from a v3.1+ binary). Without an explicit initial + /// version, the SDK's `version()` fallback returns `latest()` until + /// the first response is parsed, and the upward-only `fetch_max` + /// guard can never ratchet *down* to the older network — leaving + /// any version-dispatched encoders (e.g. the documents query) to + /// ship a too-new wire shape that the network rejects. + /// + /// Seeds `self.version` and resets `version_explicit` to `false`, so + /// auto-detect is (re-)enabled. Builder chains use last-write-wins: + /// calling `with_initial_version` after `with_version` restores + /// auto-detect rather than silently keeping it disabled. + /// + /// **Caveat**: this protection only holds for encoders whose + /// `drive_abci.query..default_current_version` is correctly pinned per + /// historical PV. New versioned encoders must follow the same per-PV pinning + /// pattern as `document_query`. + pub fn with_initial_version(mut self, version: &'static PlatformVersion) -> Self { + self.version = version; + self.version_explicit = false; + self + } + /// Configure context provider to use. /// /// Context provider is used to retrieve data contracts and quorum public keys from application state. @@ -1000,11 +1046,10 @@ impl SdkBuilder { context_provider: ArcSwapOption::new( self.context_provider.map(Arc::new)), cancel_token: self.cancel_token, nonce_cache: Default::default(), - // When auto-detecting, seed with 0 (uninitialized) so the first - // network response sets the actual version — even if it's lower - // than the binary's latest. When pinned, use the explicit version. + // Seed atomic with self.version; whether auto-detect is on + // is controlled separately by `version_explicit`. protocol_version: Arc::new(atomic::AtomicU32::new( - if self.version_explicit { self.version.protocol_version } else { 0 }, + self.version.protocol_version, )), auto_detect_protocol_version: !self.version_explicit, // Note: in the future, we need to securely initialize initial height during Sdk bootstrap or first request. @@ -1060,7 +1105,7 @@ impl SdkBuilder { Box::new(cp) } ); - let mock_sdk = MockDashPlatformSdk::new(self.version, Arc::clone(&dapi)); + let mock_sdk = MockDashPlatformSdk::new(Arc::clone(&dapi)); let mock_sdk = Arc::new(Mutex::new(mock_sdk)); let sdk= Sdk { network: self.network, @@ -1074,7 +1119,7 @@ impl SdkBuilder { proofs:self.proofs, nonce_cache: Default::default(), protocol_version: Arc::new(atomic::AtomicU32::new( - if self.version_explicit { self.version.protocol_version } else { 0 }, + self.version.protocol_version, )), auto_detect_protocol_version: !self.version_explicit, context_provider: ArcSwapOption::new(Some(Arc::new(context_provider))), @@ -1508,38 +1553,114 @@ mod test { } #[test] - fn test_default_sdk_detects_older_network_version() { + fn test_with_initial_version_seeds_to_older_network_version() { use dpp::version::PlatformVersion; - // Default SDK: auto-detect enabled, seeded at 0 (uninitialized) + // Caller knows the network is on PV 1 and seeds the auto-detect + // atomic accordingly. `version_explicit` stays false, so fetch_max + // can still ratchet upward when the network later moves to a newer PV. + let initial = PlatformVersion::get(1).expect("PV 1 exists"); let sdk = SdkBuilder::new_mock() + .with_initial_version(initial) .build() .expect("mock Sdk should be created"); - // Before any network response, version() falls back to latest() assert_eq!( - sdk.version().protocol_version, - PlatformVersion::latest().protocol_version, - "before first response, should fall back to latest" + sdk.protocol_version_number(), + 1, + "with_initial_version must seed the atomic without pinning" ); - assert_eq!(sdk.protocol_version_number(), 0, "should be uninitialized"); + assert_eq!(sdk.version().protocol_version, 1); - // Network reports version 1 (older than latest) — should be accepted + // Metadata at PV 1 is accepted (matches current seed, no ratchet needed). let metadata = ResponseMetadata { protocol_version: 1, height: 1, ..Default::default() }; - sdk.verify_response_metadata("test", &metadata) .expect("metadata should be valid"); + assert_eq!(sdk.protocol_version_number(), 1); + } + + #[test] + fn test_with_initial_version_after_with_version_restores_auto_detect() { + use dpp::version::PlatformVersion; + + // Last-write-wins composability: a later `with_initial_version` + // must re-enable auto-detect that an earlier `with_version` + // disabled. + let v_latest = PlatformVersion::latest(); + let v_old = PlatformVersion::get(1).expect("PV 1 exists"); + + let sdk = SdkBuilder::new_mock() + .with_version(v_latest) + .with_initial_version(v_old) + .build() + .expect("mock Sdk should be created"); assert_eq!( sdk.protocol_version_number(), - 1, - "default SDK must detect older network version" + v_old.protocol_version, + "with_initial_version must overwrite the prior with_version seed" + ); + assert!( + sdk.auto_detect_protocol_version, + "with_initial_version must restore auto-detect after with_version disabled it" + ); + + // Ratchet upward via metadata observation works because auto-detect is on. + let metadata = ResponseMetadata { + protocol_version: v_latest.protocol_version, + height: 1, + ..Default::default() + }; + sdk.verify_response_metadata("test", &metadata) + .expect("metadata should be valid"); + assert_eq!(sdk.protocol_version_number(), v_latest.protocol_version); + } + + #[test] + fn test_mock_version_follows_outer_sdk_atomic() { + use dpp::version::PlatformVersion; + + // Build a mock SDK with auto-detect, seeded at PV 1. After a + // metadata-driven ratchet to a newer PV, both the outer SDK's + // `version()` and the inner `MockDashPlatformSdk::version()` + // must report the same value — single source of truth. + let v_old = PlatformVersion::get(1).expect("PV 1 exists"); + let v_new = PlatformVersion::latest(); + + let mut sdk = SdkBuilder::new_mock() + .with_initial_version(v_old) + .build() + .expect("mock Sdk should be created"); + + assert_eq!(sdk.version().protocol_version, v_old.protocol_version); + { + let mock = sdk.mock(); + assert_eq!( + mock.version().protocol_version, + v_old.protocol_version, + "mock version must mirror outer SDK before ratchet" + ); + } + + let metadata = ResponseMetadata { + protocol_version: v_new.protocol_version, + height: 1, + ..Default::default() + }; + sdk.verify_response_metadata("test", &metadata) + .expect("metadata should be valid"); + + assert_eq!(sdk.version().protocol_version, v_new.protocol_version); + let mock = sdk.mock(); + assert_eq!( + mock.version().protocol_version, + v_new.protocol_version, + "mock version must follow outer ratchet (CMT-001 regression)" ); - assert_eq!(sdk.version().protocol_version, 1); } #[test_matrix([90,91,100,109,110], 100, 10, false; "valid time")] diff --git a/packages/rs-sdk/tests/fetch/common.rs b/packages/rs-sdk/tests/fetch/common.rs index 052b8b67a1b..51e4fb4b3d0 100644 --- a/packages/rs-sdk/tests/fetch/common.rs +++ b/packages/rs-sdk/tests/fetch/common.rs @@ -1,4 +1,8 @@ -use dash_sdk::{mock::Mockable, platform::Query, Sdk}; +use dash_sdk::{ + mock::Mockable, + platform::{Query, QuerySettings}, + Sdk, +}; use dpp::data_contract::config::DataContractConfig; use dpp::{data_contract::DataContractFactory, prelude::Identifier}; use hex::ToHex; @@ -127,7 +131,13 @@ pub(crate) async fn setup_sdk_for_test_case (String, Sdk) { - let key = rs_dapi_client::mock::Key::new(&query.query(true).expect("valid query")); + let request_settings = rs_dapi_client::RequestSettings::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: dpp::version::PlatformVersion::latest(), + prove: true, + }; + let key = rs_dapi_client::mock::Key::new(&query.query(&settings).expect("valid query")); let test_case_id = format!("{}_{}", name_prefix, key.encode_hex::()); // create new sdk to ensure that test cases don't interfere with each other diff --git a/packages/rs-sdk/tests/fetch/document_query_v0_v1.rs b/packages/rs-sdk/tests/fetch/document_query_v0_v1.rs new file mode 100644 index 00000000000..28081a70a03 --- /dev/null +++ b/packages/rs-sdk/tests/fetch/document_query_v0_v1.rs @@ -0,0 +1,304 @@ +//! Unit tests for the version-aware `DocumentQuery → GetDocumentsRequest` +//! encoder added to land the v3.0-testnet decode-error fix. +//! +//! Covers: +//! - V0 wire-shape parity: encoding with a PlatformVersion whose +//! `document_query.default_current_version = 0` ships the legacy +//! `getDocuments` shape (CBOR-encoded `where` / `order_by` bytes, +//! plain `uint32` limit) inside `Version::V0(...)`. +//! - V1 wire-shape parity: encoding with the latest PlatformVersion +//! ships the SQL-shaped surface (structured WhereClause / OrderClause, +//! `optional uint32` limit, selects / group_by / having / offset +//! fields) inside `Version::V1(...)`. +//! - V1-only feature rejection on V0: `group_by`, `having`, +//! `count_star()` projection — each returns `Error::Config` rather +//! than silently emitting an invalid V0 request the server would +//! round-trip and reject. +//! - Dispatch by SDK version: a `DocumentQuery` whose +//! `protocol_version_override` field points at a V0 PlatformVersion +//! round-trips through `TryFrom` as V0; default falls back to V1. +//! - `SdkBuilder::with_initial_version` semantics: builder seeds the +//! per-instance protocol_version atomic to the requested value +//! without flipping `version_explicit`, so auto-detect remains +//! active and `maybe_update_protocol_version` can still ratchet +//! upward via `fetch_max`. + +use std::sync::Arc; + +use super::common::{mock_data_contract, mock_document_type}; +use dapi_grpc::platform::v0::get_documents_request::Version as ReqVersion; +use dapi_grpc::platform::v0::GetDocumentsRequest; +use dash_sdk::{platform::documents::document_query::DocumentQuery, Error as SdkError, SdkBuilder}; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::platform_value::Value; +use dpp::version::PlatformVersion; +use drive::query::conditions::{WhereClause, WhereOperator}; +use drive::query::ordering::OrderClause; +use drive::query::SelectProjection; + +/// Build a synthetic `'static PlatformVersion` whose +/// `drive_abci.query.document_query.default_current_version` is forced +/// to `0` so the encoder dispatches onto the V0 path. Every other +/// field is cloned from `PlatformVersion::latest()` so unrelated +/// subsystems still see the binary's real version layout. +fn v0_dispatch_version() -> &'static PlatformVersion { + let mut pv = PlatformVersion::latest().clone(); + pv.drive_abci.query.document_query.default_current_version = 0; + pv.drive_abci.query.document_query.min_version = 0; + pv.drive_abci.query.document_query.max_version = 0; + Box::leak(Box::new(pv)) +} + +fn build_basic_document_query() -> DocumentQuery { + let document_type = mock_document_type(); + let data_contract = mock_data_contract(Some(&document_type)); + DocumentQuery::new(Arc::new(data_contract), document_type.name()) + .expect("build DocumentQuery") + .with_where(WhereClause { + field: "a".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("hello".to_string()), + }) + .with_order_by(OrderClause { + field: "a".to_string(), + ascending: true, + }) + .with_limit(7) +} + +#[test] +fn v1_wire_shape_with_latest_platform_version() { + let q = build_basic_document_query(); + let req: GetDocumentsRequest = q + .try_into_request_for_version(PlatformVersion::latest()) + .expect("encode V1"); + + match req.version { + Some(ReqVersion::V1(v1)) => { + assert_eq!(v1.document_type, "document_type_name"); + assert_eq!(v1.where_clauses.len(), 1); + assert_eq!(v1.order_by.len(), 1); + assert_eq!(v1.limit, Some(7)); + assert!(v1.prove); + // The default `SelectProjection::documents()` round-trips as a + // single-element `selects` list — the V1 wire surface keeps + // selects as a `repeated` field for multi-projection futures. + assert_eq!(v1.selects.len(), 1); + assert!(v1.group_by.is_empty()); + assert!(v1.having.is_empty()); + assert_eq!(v1.offset, None); + } + other => panic!("expected V1 wire, got {other:?}"), + } +} + +#[test] +fn v0_wire_shape_with_forced_v0_platform_version() { + let q = build_basic_document_query(); + let req: GetDocumentsRequest = q + .try_into_request_for_version(v0_dispatch_version()) + .expect("encode V0"); + + match req.version { + Some(ReqVersion::V0(v0)) => { + assert_eq!(v0.document_type, "document_type_name"); + assert_eq!(v0.limit, 7); + assert!(v0.prove); + // V0 ships CBOR-encoded `where` / `order_by` bytes; the + // shape contract is "decodes back into Value::Array of + // 3-tuples / 2-tuples". The server-side decoder consumes + // these via `ciborium::de::from_reader` then matches on + // `Value::Array(clauses)` — round-trip here so the test + // catches a future regression in either direction. + assert!(!v0.r#where.is_empty(), "V0 where bytes must be non-empty"); + let where_value: ciborium::Value = + ciborium::de::from_reader(v0.r#where.as_slice()).expect("decode where CBOR"); + let arr = where_value.as_array().expect("where root is array"); + assert_eq!(arr.len(), 1); + let clause = arr[0].as_array().expect("clause is array"); + assert_eq!(clause.len(), 3); + assert_eq!(clause[0].as_text(), Some("a")); + assert_eq!(clause[1].as_text(), Some("=")); + + assert!( + !v0.order_by.is_empty(), + "V0 order_by bytes must be non-empty" + ); + let order_value: ciborium::Value = + ciborium::de::from_reader(v0.order_by.as_slice()).expect("decode order CBOR"); + let arr = order_value.as_array().expect("order_by root is array"); + assert_eq!(arr.len(), 1); + let clause = arr[0].as_array().expect("order clause is array"); + assert_eq!(clause.len(), 2); + assert_eq!(clause[0].as_text(), Some("a")); + assert_eq!(clause[1].as_text(), Some("asc")); + } + other => panic!("expected V0 wire, got {other:?}"), + } +} + +#[test] +fn v0_rejects_count_star_projection() { + let q = build_basic_document_query().with_select(SelectProjection::count_star()); + let err = q + .try_into_request_for_version(v0_dispatch_version()) + .expect_err("count_star on v0 must reject"); + match err { + SdkError::Config(msg) => assert!( + msg.contains("v3.1+"), + "config error should cite v3.1+ minimum, got: {msg}" + ), + other => panic!("expected Error::Config, got {other:?}"), + } +} + +#[test] +fn v0_rejects_group_by() { + let q = build_basic_document_query().with_group_by("a"); + let err = q + .try_into_request_for_version(v0_dispatch_version()) + .expect_err("group_by on v0 must reject"); + assert!(matches!(err, SdkError::Config(_))); +} + +#[test] +fn v0_rejects_having() { + use drive::query::{ + HavingAggregate, HavingAggregateFunction, HavingClause, HavingOperator, HavingRightOperand, + }; + let q = build_basic_document_query().with_having(vec![HavingClause { + aggregate: HavingAggregate { + function: HavingAggregateFunction::Count, + field: String::new(), + }, + operator: HavingOperator::GreaterThan, + right: HavingRightOperand::Value(Value::U64(0)), + }]); + let err = q + .try_into_request_for_version(v0_dispatch_version()) + .expect_err("having on v0 must reject"); + assert!(matches!(err, SdkError::Config(_))); +} + +#[test] +fn encoder_dispatches_v0_via_query_settings_without_sdk() { + use dash_sdk::platform::{Query, QuerySettings}; + use rs_dapi_client::RequestSettings; + + // The whole point of QuerySettings: encoder is testable without + // `Sdk::new_mock()`. Construct the context directly from a + // PlatformVersion whose document_query is pinned to V0 dispatch + // and assert the wire shape comes out V0. + let v0_pv = v0_dispatch_version(); + let request_settings = RequestSettings::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: v0_pv, + prove: true, + }; + let q = build_basic_document_query(); + let req: GetDocumentsRequest = q.query(&settings).expect("encode via QuerySettings"); + assert!( + matches!(req.version, Some(ReqVersion::V0(_))), + "expected V0 dispatch when settings.protocol_version pins document_query to v0" + ); + + // Same query, latest PlatformVersion (V1 dispatch) — should now + // emit V1 wire bytes through the same code path. + let latest_settings = QuerySettings { + request_settings: &request_settings, + protocol_version: PlatformVersion::latest(), + prove: true, + }; + let q = build_basic_document_query(); + let req: GetDocumentsRequest = q.query(&latest_settings).expect("encode via QuerySettings"); + assert!( + matches!(req.version, Some(ReqVersion::V1(_))), + "expected V1 dispatch when settings.protocol_version is latest" + ); +} + +#[test] +fn sdk_builder_with_initial_version_seeds_atomic_without_pinning() { + // Auto-detect default: the atomic seeds to `self.version` (which + // defaults to `latest()`). `version()` therefore returns `latest()` + // until the first response ratchets the atomic upward. + let sdk_default = SdkBuilder::new_mock().build().expect("mock sdk"); + assert_eq!( + sdk_default.version().protocol_version, + PlatformVersion::latest().protocol_version + ); + + // `with_initial_version` seeds the atomic to the requested PV's + // protocol_version. Auto-detect REMAINS on (this is the contract + // distinguishing it from `with_version`): a future + // `maybe_update_protocol_version(higher)` call would ratchet + // upward via `fetch_max`. + let pv_first = PlatformVersion::get(1).expect("v1 is always known"); + let sdk_initial = SdkBuilder::new_mock() + .with_initial_version(pv_first) + .build() + .expect("mock sdk with initial version"); + assert_eq!( + sdk_initial.protocol_version_number(), + pv_first.protocol_version + ); + // `version()` reflects the seeded value — no auto-detect bump + // has occurred yet (no network responses parsed). + assert_eq!( + sdk_initial.version().protocol_version, + pv_first.protocol_version + ); +} + +/// PROTOCOL_VERSION_11 corresponds to Dash Platform v3.0 (testnet at the +/// time of this work). Its `document_query` bounds must pin to V0 so an +/// SDK seeded at PV_11 emits V0 wire bytes that v3.0 HPMNs accept. +#[test] +fn protocol_version_for_v3_0_pins_document_query_to_v0() { + let pv = PlatformVersion::get(11).expect("PROTOCOL_VERSION_11 exists"); + assert_eq!( + pv.drive_abci.query.document_query.default_current_version, + 0 + ); + assert_eq!(pv.drive_abci.query.document_query.max_version, 0); +} + +/// PROTOCOL_VERSION_12 corresponds to v3.1-dev. Its `document_query` +/// bounds must keep V1 semantics (max=1, default=1) — re-binding PV_11 +/// to V0 must not affect PV_12. +#[test] +fn protocol_version_for_v3_1_dev_keeps_document_query_v1() { + let pv = PlatformVersion::get(12).expect("PROTOCOL_VERSION_12 exists"); + assert_eq!( + pv.drive_abci.query.document_query.default_current_version, + 1 + ); + assert_eq!(pv.drive_abci.query.document_query.max_version, 1); +} + +/// Wallet-team end-to-end shape: an SDK built with +/// `with_initial_version(PROTOCOL_VERSION_11)` (Dash Platform v3.0) must +/// dispatch to the V0 encoder — proving the full plumbing works +/// without monkey-patching `PlatformVersion::latest()` clones. +#[test] +fn document_query_dispatches_v0_when_sdk_initial_version_is_v3_0_pv() { + use dash_sdk::platform::{Query, QuerySettings}; + use rs_dapi_client::RequestSettings; + + let pv_v3_0 = PlatformVersion::get(11).expect("PROTOCOL_VERSION_11 exists"); + let request_settings = RequestSettings::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: pv_v3_0, + prove: true, + }; + let q = build_basic_document_query(); + let req: GetDocumentsRequest = q + .query(&settings) + .expect("encode for v3.0 PV via QuerySettings"); + assert!( + matches!(req.version, Some(ReqVersion::V0(_))), + "expected V0 dispatch for PROTOCOL_VERSION_11" + ); +} diff --git a/packages/rs-sdk/tests/fetch/mod.rs b/packages/rs-sdk/tests/fetch/mod.rs index b743d86e430..f611f30be02 100644 --- a/packages/rs-sdk/tests/fetch/mod.rs +++ b/packages/rs-sdk/tests/fetch/mod.rs @@ -19,6 +19,7 @@ mod contested_resource_voters; mod data_contract; mod document; mod document_count; +mod document_query_v0_v1; mod epoch; mod evonode; mod generated_data; diff --git a/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs b/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs index edbe3c315e0..21afd47ee49 100644 --- a/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs +++ b/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs @@ -1,8 +1,10 @@ use crate::fetch::common::setup_logs; use dash_sdk::platform::tokens::token_contract_info::TokenContractInfoQuery; -use dash_sdk::platform::{Fetch, Identifier, Query}; +use dash_sdk::platform::{Fetch, Identifier, Query, QuerySettings}; use dash_sdk::Sdk; use dpp::tokens::contract_info::TokenContractInfo; +use dpp::version::PlatformVersion; +use rs_dapi_client::RequestSettings; #[tokio::test] async fn test_token_contract_info_fetch_by_identifier() { @@ -49,7 +51,13 @@ async fn test_token_contract_info_query_prove_true() { let token_id = Identifier::from_bytes(&[3u8; 32]).unwrap(); let query = TokenContractInfoQuery { token_id }; - let request = query.query(true).unwrap(); + let request_settings = RequestSettings::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: PlatformVersion::latest(), + prove: true, + }; + let request = query.query(&settings).unwrap(); match request.version.unwrap() { dapi_grpc::platform::v0::get_token_contract_info_request::Version::V0(v0) => { @@ -64,7 +72,13 @@ async fn test_token_contract_info_query_prove_false() { let token_id = Identifier::from_bytes(&[4u8; 32]).unwrap(); let query = TokenContractInfoQuery { token_id }; - let request = query.query(false).unwrap(); + let request_settings = RequestSettings::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: PlatformVersion::latest(), + prove: false, + }; + let request = query.query(&settings).unwrap(); match request.version.unwrap() { dapi_grpc::platform::v0::get_token_contract_info_request::Version::V0(v0) => { diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json deleted file mode 100644 index bcf43e9910e..00000000000 Binary files a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index d7eb96c1aa9..1c4e12102f8 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDocumentsRequest_02213251619b5f2925ddad3e4e0a2380e57616a701bfbde50d048d23e0e09094.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDocumentsRequest_02213251619b5f2925ddad3e4e0a2380e57616a701bfbde50d048d23e0e09094.json new file mode 100644 index 00000000000..d07e2039b5f Binary files /dev/null and b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDocumentsRequest_02213251619b5f2925ddad3e4e0a2380e57616a701bfbde50d048d23e0e09094.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-303c6a7b1e3aa25fa847ce5f6d6f39c3252081bcf291d632bbf38d43878d4777.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-303c6a7b1e3aa25fa847ce5f6d6f39c3252081bcf291d632bbf38d43878d4777.json new file mode 100644 index 00000000000..428df46fdd8 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-303c6a7b1e3aa25fa847ce5f6d6f39c3252081bcf291d632bbf38d43878d4777.json @@ -0,0 +1 @@ +b67f0be8837074018cb384fc49c8f312bfac6377b96153ae204297362b62f22b90bf06a41559b03b00270c203ebeb3c6 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json deleted file mode 100644 index e18b2a7deac..00000000000 --- a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json +++ /dev/null @@ -1 +0,0 @@ -b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_2fd2f7aebe5686d4e4179323b49e8920dea81c3f44b9549c238dcb82cccc9923.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_2fd2f7aebe5686d4e4179323b49e8920dea81c3f44b9549c238dcb82cccc9923.json deleted file mode 100644 index 281464984a0..00000000000 Binary files a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_2fd2f7aebe5686d4e4179323b49e8920dea81c3f44b9549c238dcb82cccc9923.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 038ae04f81d..1c4e12102f8 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDocumentsRequest_331458c78645abf6543c22204af22570c7fa61490e1c5c381c73a4a3e1bacc84.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDocumentsRequest_331458c78645abf6543c22204af22570c7fa61490e1c5c381c73a4a3e1bacc84.json new file mode 100644 index 00000000000..a8aa925b846 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDocumentsRequest_331458c78645abf6543c22204af22570c7fa61490e1c5c381c73a4a3e1bacc84.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-303c6a7b1e3aa25fa847ce5f6d6f39c3252081bcf291d632bbf38d43878d4777.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-303c6a7b1e3aa25fa847ce5f6d6f39c3252081bcf291d632bbf38d43878d4777.json new file mode 100644 index 00000000000..428df46fdd8 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-303c6a7b1e3aa25fa847ce5f6d6f39c3252081bcf291d632bbf38d43878d4777.json @@ -0,0 +1 @@ +b67f0be8837074018cb384fc49c8f312bfac6377b96153ae204297362b62f22b90bf06a41559b03b00270c203ebeb3c6 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json deleted file mode 100644 index e18b2a7deac..00000000000 --- a/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json +++ /dev/null @@ -1 +0,0 @@ -b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json deleted file mode 100644 index 2d5fcb23be0..00000000000 Binary files a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_2a42b0afe6c6f58b02d8152142acec7d11a37410433366315d1103f81859344b.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_4816e45a0ba02d69c291f23322410a8556ecf1145e99c87071cc8998a97d7ccb.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_4816e45a0ba02d69c291f23322410a8556ecf1145e99c87071cc8998a97d7ccb.json deleted file mode 100644 index 49c3fe8af1f..00000000000 Binary files a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_4816e45a0ba02d69c291f23322410a8556ecf1145e99c87071cc8998a97d7ccb.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 603afa7eb28..48078b4ace6 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_GetDocumentsRequest_02213251619b5f2925ddad3e4e0a2380e57616a701bfbde50d048d23e0e09094.json b/packages/rs-sdk/tests/vectors/document_read/msg_GetDocumentsRequest_02213251619b5f2925ddad3e4e0a2380e57616a701bfbde50d048d23e0e09094.json new file mode 100644 index 00000000000..599dc0adc3d Binary files /dev/null and b/packages/rs-sdk/tests/vectors/document_read/msg_GetDocumentsRequest_02213251619b5f2925ddad3e4e0a2380e57616a701bfbde50d048d23e0e09094.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_GetDocumentsRequest_2496027c61fad2723bcec60b574423e3d41ce93dde03d5299b46b8e4858a0e3b.json b/packages/rs-sdk/tests/vectors/document_read/msg_GetDocumentsRequest_2496027c61fad2723bcec60b574423e3d41ce93dde03d5299b46b8e4858a0e3b.json new file mode 100644 index 00000000000..8f3922f9453 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/document_read/msg_GetDocumentsRequest_2496027c61fad2723bcec60b574423e3d41ce93dde03d5299b46b8e4858a0e3b.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json new file mode 100644 index 00000000000..c48be3d8ae7 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json @@ -0,0 +1 @@ +8791ef8bb5b32600a62a220d0afc2071ad64c9a41e97531fcd86de8ed7ef655425ce88687e65f5067d88f687c5a3abec \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json deleted file mode 100644 index e18b2a7deac..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json +++ /dev/null @@ -1 +0,0 @@ -b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json index e6ba55bd212..15a8a306c7d 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json and b/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json new file mode 100644 index 00000000000..c48be3d8ae7 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json @@ -0,0 +1 @@ +8791ef8bb5b32600a62a220d0afc2071ad64c9a41e97531fcd86de8ed7ef655425ce88687e65f5067d88f687c5a3abec \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json deleted file mode 100644 index e18b2a7deac..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json +++ /dev/null @@ -1 +0,0 @@ -b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_f531f69255dae40cef880290c177ff33d2448d30f2527374349b9f507b44c5c1.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_f531f69255dae40cef880290c177ff33d2448d30f2527374349b9f507b44c5c1.json deleted file mode 100644 index 6a8d8348047..00000000000 Binary files a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_f531f69255dae40cef880290c177ff33d2448d30f2527374349b9f507b44c5c1.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 1382d46be43..48078b4ace6 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDocumentsRequest_9256bdd6fc78e23f941d17d93b0230cf0f134e114c5e23ad7f08ed94c92f962f.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDocumentsRequest_9256bdd6fc78e23f941d17d93b0230cf0f134e114c5e23ad7f08ed94c92f962f.json new file mode 100644 index 00000000000..0c39c2f2b36 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDocumentsRequest_9256bdd6fc78e23f941d17d93b0230cf0f134e114c5e23ad7f08ed94c92f962f.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json new file mode 100644 index 00000000000..c48be3d8ae7 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-1c97c16f6b472d0beadfb1bb83aadc440dc2be19879e09aeb342056f8f58e0fe.json @@ -0,0 +1 @@ +8791ef8bb5b32600a62a220d0afc2071ad64c9a41e97531fcd86de8ed7ef655425ce88687e65f5067d88f687c5a3abec \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json deleted file mode 100644 index e18b2a7deac..00000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-3603d12872604475619be7ad682f8339ad60debd43b3f430bd12d51eac268936.json +++ /dev/null @@ -1 +0,0 @@ -b751df5b612ece651a4d290fa95fab328d5b186b84fc88b103bb45cdf6d3815620b74daa0d72067d74ea86da595c6a59 \ No newline at end of file