From 0f26760b78bf5c3e48fb090332416bad4eebb031 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 3 Mar 2025 21:03:26 +0700 Subject: [PATCH 1/2] temp work --- .../protos/platform/v0/platform.proto | 26 ++ .../mod.rs | 67 +++++ .../v0/mod.rs | 168 +++++++++++++ .../mod.rs | 6 +- .../v0/mod.rs | 8 +- .../src/query/identity_based_queries/mod.rs | 3 +- packages/rs-drive-abci/src/query/service.rs | 44 +--- .../tests/strategy_tests/query.rs | 2 +- packages/rs-drive-proof-verifier/src/proof.rs | 2 +- .../mod.rs | 53 ++++ .../v0/mod.rs | 53 ++++ .../mod.rs | 48 +++- .../v0/mod.rs | 36 ++- .../fetch/fetch_by_public_key_hashes/mod.rs | 6 +- .../src/drive/identity/fetch/prove/mod.rs | 1 + .../mod.rs | 52 ++++ .../v0/mod.rs | 234 ++++++++++++++++++ .../v0/mod.rs | 2 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 2 +- .../src/drive/identity/fetch/queries/mod.rs | 35 ++- packages/rs-drive/src/verify/identity/mod.rs | 8 +- .../v0/mod.rs | 2 +- .../mod.rs | 66 +++++ .../v0/mod.rs | 68 +++++ .../mod.rs | 6 +- .../v0/mod.rs | 4 +- .../mod.rs | 65 +++++ .../v0/mod.rs | 78 ++++++ .../mod.rs | 8 +- .../v0/mod.rs | 2 +- .../mod.rs | 8 +- .../v0/mod.rs | 2 +- .../drive_abci_query_versions/mod.rs | 2 +- .../drive_abci_query_versions/v1.rs | 2 +- .../drive_identity_method_versions/mod.rs | 2 + .../drive_identity_method_versions/v1.rs | 2 + .../drive_verify_method_versions/mod.rs | 6 +- .../drive_verify_method_versions/v1.rs | 6 +- .../src/version/mocks/v2_test.rs | 2 +- 40 files changed, 1097 insertions(+), 92 deletions(-) create mode 100644 packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs create mode 100644 packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs rename packages/rs-drive-abci/src/query/identity_based_queries/{identity_by_public_key_hash => identity_by_unique_public_key_hash}/mod.rs (92%) rename packages/rs-drive-abci/src/query/identity_based_queries/{identity_by_public_key_hash => identity_by_unique_public_key_hash}/v0/mod.rs (94%) create mode 100644 packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs create mode 100644 packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs create mode 100644 packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs create mode 100644 packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs create mode 100644 packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs create mode 100644 packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs rename packages/rs-drive/src/verify/identity/{verify_full_identity_by_public_key_hash => verify_full_identity_by_unique_public_key_hash}/mod.rs (89%) rename packages/rs-drive/src/verify/identity/{verify_full_identity_by_public_key_hash => verify_full_identity_by_unique_public_key_hash}/v0/mod.rs (96%) create mode 100644 packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs create mode 100644 packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs rename packages/rs-drive/src/verify/identity/{verify_identity_id_by_public_key_hash => verify_identity_id_by_unique_public_key_hash}/mod.rs (86%) rename packages/rs-drive/src/verify/identity/{verify_identity_id_by_public_key_hash => verify_identity_id_by_unique_public_key_hash}/v0/mod.rs (98%) rename packages/rs-drive/src/verify/identity/{verify_identity_ids_by_public_key_hashes => verify_identity_ids_by_unique_public_key_hashes}/mod.rs (87%) rename packages/rs-drive/src/verify/identity/{verify_identity_ids_by_public_key_hashes => verify_identity_ids_by_unique_public_key_hashes}/v0/mod.rs (98%) diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index d35efdd131a..5cf0a4c7fdd 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -33,6 +33,8 @@ service Platform { rpc getDocuments(GetDocumentsRequest) returns (GetDocumentsResponse); rpc getIdentityByPublicKeyHash(GetIdentityByPublicKeyHashRequest) returns (GetIdentityByPublicKeyHashResponse); + rpc getIdentityByNonUniquePublicKeyHash(GetIdentityByNonUniquePublicKeyHashRequest) + returns (GetIdentityByNonUniquePublicKeyHashResponse); rpc waitForStateTransitionResult(WaitForStateTransitionResultRequest) returns (WaitForStateTransitionResultResponse); rpc getConsensusParams(GetConsensusParamsRequest) @@ -620,6 +622,30 @@ message GetIdentityByPublicKeyHashResponse { oneof version { GetIdentityByPublicKeyHashResponseV0 v0 = 1; } } +message GetIdentityByNonUniquePublicKeyHashRequest { + message GetIdentityByNonUniquePublicKeyHashRequestV0 { + bytes public_key_hash = 1; + optional bytes start_after = 2; // Give one result after a previous result + bool prove = 3; + } + oneof version { GetIdentityByNonUniquePublicKeyHashRequestV0 v0 = 1; } +} + +message GetIdentityByNonUniquePublicKeyHashResponse { + message GetIdentityByNonUniquePublicKeyHashResponseV0 { + message IdentityResponse { + optional bytes identity = 1; + } + oneof result { + IdentityResponse identity = 1; + Proof proof = 2; + } + + ResponseMetadata metadata = 3; // Metadata about the blockchain state + } + oneof version { GetIdentityByNonUniquePublicKeyHashResponseV0 v0 = 1; } +} + message WaitForStateTransitionResultRequest { message WaitForStateTransitionResultRequestV0 { bytes state_transition_hash = 1; // The hash of the state transition to wait for diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs new file mode 100644 index 00000000000..8bfd4ed12e3 --- /dev/null +++ b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs @@ -0,0 +1,67 @@ +use crate::error::query::QueryError; +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; +use crate::query::QueryValidationResult; +use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_request::Version as RequestVersion; +use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::Version as ResponseVersion; +use dapi_grpc::platform::v0::{GetIdentityByNonUniquePublicKeyHashRequest, GetIdentityByNonUniquePublicKeyHashResponse, GetIdentityByPublicKeyHashResponse}; +use dpp::version::PlatformVersion; + +mod v0; + +impl Platform { + /// Querying of an identity by a public key hash + pub fn query_identity_by_non_unique_public_key_hash( + &self, + GetIdentityByNonUniquePublicKeyHashRequest { version }: GetIdentityByNonUniquePublicKeyHashRequest, + platform_state: &PlatformState, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let Some(version) = version else { + return Ok(QueryValidationResult::new_with_error( + QueryError::DecodingError( + "could not decode identity by public key non unique hash query".to_string(), + ), + )); + }; + + let feature_version_bounds = &platform_version + .drive_abci + .query + .identity_based_queries + .identity_by_unique_public_key_hash; + + let feature_version = match &version { + RequestVersion::V0(_) => 0, + }; + + if !feature_version_bounds.check_version(feature_version) { + return Ok(QueryValidationResult::new_with_error( + QueryError::UnsupportedQueryVersion( + "identity_by_non_unique_public_key_hash".to_string(), + feature_version_bounds.min_version, + feature_version_bounds.max_version, + platform_version.protocol_version, + feature_version, + ), + )); + } + + match version { + RequestVersion::V0(request_v0) => { + let request = self.query_identity_by_non_unique_public_key_hash_v0( + request_v0, + platform_state, + platform_version, + )?; + + Ok( + request.map(|response_v0| GetIdentityByNonUniquePublicKeyHashResponse { + version: Some(ResponseVersion::V0(response_v0)), + }), + ) + } + } + } +} diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs new file mode 100644 index 00000000000..07f23174845 --- /dev/null +++ b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs @@ -0,0 +1,168 @@ +use crate::error::query::QueryError; +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; +use crate::query::QueryValidationResult; +use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_request::GetIdentityByNonUniquePublicKeyHashRequestV0; +use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::{ + get_identity_by_non_unique_public_key_hash_response_v0, GetIdentityByNonUniquePublicKeyHashResponseV0, +}; +use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::get_identity_by_non_unique_public_key_hash_response_v0::IdentityResponse; +use dpp::check_validation_result_with_data; +use dpp::platform_value::{Bytes20, Bytes32}; +use dpp::serialization::PlatformSerializable; +use dpp::validation::ValidationResult; +use dpp::version::PlatformVersion; + +impl Platform { + pub(super) fn query_identity_by_non_unique_public_key_hash_v0( + &self, + GetIdentityByNonUniquePublicKeyHashRequestV0 { + public_key_hash, + start_after, + prove, + }: GetIdentityByNonUniquePublicKeyHashRequestV0, + platform_state: &PlatformState, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let public_key_hash = + check_validation_result_with_data!(Bytes20::from_vec(public_key_hash) + .map(|bytes| bytes.0) + .map_err(|_| QueryError::InvalidArgument( + "public key hash must be 20 bytes long".to_string() + ))); + + let start_after = if let Some(start_after) = start_after { + Some(check_validation_result_with_data!(Bytes32::from_vec(start_after) + .map(|bytes| bytes.0) + .map_err(|_| QueryError::InvalidArgument( + "public key hash must be 20 bytes long".to_string() + )))) + } else { + None + }; + + + let response = if prove { + let proof = self.drive.prove_full_identity_by_non_unique_public_key_hash( + public_key_hash, + start_after, + None, + platform_version, + )?; + + GetIdentityByNonUniquePublicKeyHashResponseV0 { + result: Some(get_identity_by_non_unique_public_key_hash_response_v0::Result::Proof( + self.response_proof_v0(platform_state, proof), + )), + metadata: Some(self.response_metadata_v0(platform_state)), + } + } else { + let maybe_identity = self.drive.fetch_full_identity_by_non_unique_public_key_hash( + public_key_hash, + start_after, + None, + platform_version, + )?; + + let serialized_identity = maybe_identity.map(|identity| + + identity + .serialize_consume_to_bytes() + .map_err(Error::Protocol) + + ).transpose()?; + + + GetIdentityByNonUniquePublicKeyHashResponseV0 { + metadata: Some(self.response_metadata_v0(platform_state)), + result: Some( + get_identity_by_non_unique_public_key_hash_response_v0::Result::Identity( + IdentityResponse { + identity: serialized_identity, + }, + ), + ), + } + }; + + Ok(QueryValidationResult::new_with_data(response)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::query::tests::setup_platform; + use dpp::dashcore::Network; + use dapi_grpc::platform::v0::ResponseMetadata; + + #[test] + fn test_invalid_public_key_hash() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let request = GetIdentityByNonUniquePublicKeyHashRequestV0 { + public_key_hash: vec![0; 8], + start_after: None, + prove: false, + }; + + let result = platform + .query_identity_by_non_unique_public_key_hash_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(matches!( + result.errors.as_slice(), + [QueryError::InvalidArgument(msg)] if msg == &"public key hash must be 20 bytes long".to_string() + )); + } + + #[test] + fn test_identity_not_found() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let public_key_hash = vec![0; 20]; + let request = GetIdentityByNonUniquePublicKeyHashRequestV0 { + public_key_hash: public_key_hash.clone(), + start_after: None, + prove: false, + }; + + let result = platform + .query_identity_by_non_unique_public_key_hash_v0(request, &state, version) + .expect("expected query to succeed"); + + assert_eq!(result.data, Some(GetIdentityByNonUniquePublicKeyHashResponseV0 { + metadata: Some(ResponseMetadata { height: 0, core_chain_locked_height: 0, epoch: 0, time_ms: 0, protocol_version: 9, chain_id: "chain_id".to_string() }), + result: Some(get_identity_by_non_unique_public_key_hash_response_v0::Result::Identity(IdentityResponse { + identity: None, + })), + })); + } + + #[test] + fn test_identity_absence_proof() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let public_key_hash = vec![0; 20]; + let request = GetIdentityByNonUniquePublicKeyHashRequestV0 { + public_key_hash: public_key_hash.clone(), + start_after: None, + prove: true, + }; + + let result = platform + .query_identity_by_non_unique_public_key_hash_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(matches!( + result.data, + Some(GetIdentityByNonUniquePublicKeyHashResponseV0 { + result: Some(get_identity_by_non_unique_public_key_hash_response_v0::Result::Proof( + _ + )), + metadata: Some(_), + }) + )); + } +} diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_public_key_hash/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_unique_public_key_hash/mod.rs similarity index 92% rename from packages/rs-drive-abci/src/query/identity_based_queries/identity_by_public_key_hash/mod.rs rename to packages/rs-drive-abci/src/query/identity_based_queries/identity_by_unique_public_key_hash/mod.rs index db20b658b6f..2585d26afb8 100644 --- a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_public_key_hash/mod.rs +++ b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_unique_public_key_hash/mod.rs @@ -32,7 +32,7 @@ impl Platform { .drive_abci .query .identity_based_queries - .identity_by_public_key_hash; + .identity_by_unique_public_key_hash; let feature_version = match &version { RequestVersion::V0(_) => 0, @@ -41,7 +41,7 @@ impl Platform { if !feature_version_bounds.check_version(feature_version) { return Ok(QueryValidationResult::new_with_error( QueryError::UnsupportedQueryVersion( - "identity_by_public_key_hash".to_string(), + "identity_by_unique_public_key_hash".to_string(), feature_version_bounds.min_version, feature_version_bounds.max_version, platform_version.protocol_version, @@ -52,7 +52,7 @@ impl Platform { match version { RequestVersion::V0(request_v0) => { - let request = self.query_identity_by_public_key_hash_v0( + let request = self.query_identity_by_unique_public_key_hash_v0( request_v0, platform_state, platform_version, diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_public_key_hash/v0/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_unique_public_key_hash/v0/mod.rs similarity index 94% rename from packages/rs-drive-abci/src/query/identity_based_queries/identity_by_public_key_hash/v0/mod.rs rename to packages/rs-drive-abci/src/query/identity_based_queries/identity_by_unique_public_key_hash/v0/mod.rs index 0d3db5c8023..012f289e027 100644 --- a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_public_key_hash/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_unique_public_key_hash/v0/mod.rs @@ -14,7 +14,7 @@ use dpp::validation::ValidationResult; use dpp::version::PlatformVersion; impl Platform { - pub(super) fn query_identity_by_public_key_hash_v0( + pub(super) fn query_identity_by_unique_public_key_hash_v0( &self, GetIdentityByPublicKeyHashRequestV0 { public_key_hash, @@ -91,7 +91,7 @@ mod tests { }; let result = platform - .query_identity_by_public_key_hash_v0(request, &state, version) + .query_identity_by_unique_public_key_hash_v0(request, &state, version) .expect("expected query to succeed"); assert!(matches!( @@ -111,7 +111,7 @@ mod tests { }; let result = platform - .query_identity_by_public_key_hash_v0(request, &state, version) + .query_identity_by_unique_public_key_hash_v0(request, &state, version) .expect("expected query to succeed"); assert!(matches!( @@ -131,7 +131,7 @@ mod tests { }; let result = platform - .query_identity_by_public_key_hash_v0(request, &state, version) + .query_identity_by_unique_public_key_hash_v0(request, &state, version) .expect("expected query to succeed"); assert!(matches!( diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs index 29fea765215..f42ff1c4412 100644 --- a/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs +++ b/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs @@ -3,7 +3,8 @@ mod balance_and_revision; mod balances; mod identities_contract_keys; mod identity; -mod identity_by_public_key_hash; +mod identity_by_unique_public_key_hash; +mod identity_by_non_unique_public_key_hash; mod identity_contract_nonce; mod identity_nonce; mod keys; diff --git a/packages/rs-drive-abci/src/query/service.rs b/packages/rs-drive-abci/src/query/service.rs index 156ae629983..09a0dc9853e 100644 --- a/packages/rs-drive-abci/src/query/service.rs +++ b/packages/rs-drive-abci/src/query/service.rs @@ -9,40 +9,7 @@ use crate::rpc::core::DefaultCoreRPC; use crate::utils::spawn_blocking_task_with_name_if_supported; use async_trait::async_trait; use dapi_grpc::platform::v0::platform_server::Platform as PlatformService; -use dapi_grpc::platform::v0::{ - BroadcastStateTransitionRequest, BroadcastStateTransitionResponse, GetConsensusParamsRequest, - GetConsensusParamsResponse, GetContestedResourceIdentityVotesRequest, - GetContestedResourceIdentityVotesResponse, GetContestedResourceVoteStateRequest, - GetContestedResourceVoteStateResponse, GetContestedResourceVotersForIdentityRequest, - GetContestedResourceVotersForIdentityResponse, GetContestedResourcesRequest, - GetContestedResourcesResponse, GetCurrentQuorumsInfoRequest, GetCurrentQuorumsInfoResponse, - GetDataContractHistoryRequest, GetDataContractHistoryResponse, GetDataContractRequest, - GetDataContractResponse, GetDataContractsRequest, GetDataContractsResponse, - GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, - GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, - GetEvonodesProposedEpochBlocksResponse, GetGroupActionSignersRequest, - GetGroupActionSignersResponse, GetGroupActionsRequest, GetGroupActionsResponse, - GetGroupInfoRequest, GetGroupInfoResponse, GetGroupInfosRequest, GetGroupInfosResponse, - GetIdentitiesBalancesRequest, GetIdentitiesBalancesResponse, GetIdentitiesContractKeysRequest, - GetIdentitiesContractKeysResponse, GetIdentitiesTokenBalancesRequest, - GetIdentitiesTokenBalancesResponse, GetIdentitiesTokenInfosRequest, - GetIdentitiesTokenInfosResponse, GetIdentityBalanceAndRevisionRequest, - GetIdentityBalanceAndRevisionResponse, GetIdentityBalanceRequest, GetIdentityBalanceResponse, - GetIdentityByPublicKeyHashRequest, GetIdentityByPublicKeyHashResponse, - GetIdentityContractNonceRequest, GetIdentityContractNonceResponse, GetIdentityKeysRequest, - GetIdentityKeysResponse, GetIdentityNonceRequest, GetIdentityNonceResponse, GetIdentityRequest, - GetIdentityResponse, GetIdentityTokenBalancesRequest, GetIdentityTokenBalancesResponse, - GetIdentityTokenInfosRequest, GetIdentityTokenInfosResponse, GetPathElementsRequest, - GetPathElementsResponse, GetPrefundedSpecializedBalanceRequest, - GetPrefundedSpecializedBalanceResponse, GetProofsRequest, GetProofsResponse, - GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, - GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, - GetStatusRequest, GetStatusResponse, GetTokenPreProgrammedDistributionsRequest, - GetTokenPreProgrammedDistributionsResponse, GetTokenStatusesRequest, GetTokenStatusesResponse, - GetTokenTotalSupplyRequest, GetTokenTotalSupplyResponse, GetTotalCreditsInPlatformRequest, - GetTotalCreditsInPlatformResponse, GetVotePollsByEndDateRequest, GetVotePollsByEndDateResponse, - WaitForStateTransitionResultRequest, WaitForStateTransitionResultResponse, -}; +use dapi_grpc::platform::v0::{BroadcastStateTransitionRequest, BroadcastStateTransitionResponse, GetConsensusParamsRequest, GetConsensusParamsResponse, GetContestedResourceIdentityVotesRequest, GetContestedResourceIdentityVotesResponse, GetContestedResourceVoteStateRequest, GetContestedResourceVoteStateResponse, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetContestedResourcesRequest, GetContestedResourcesResponse, GetCurrentQuorumsInfoRequest, GetCurrentQuorumsInfoResponse, GetDataContractHistoryRequest, GetDataContractHistoryResponse, GetDataContractRequest, GetDataContractResponse, GetDataContractsRequest, GetDataContractsResponse, GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, GetEvonodesProposedEpochBlocksResponse, GetGroupActionSignersRequest, GetGroupActionSignersResponse, GetGroupActionsRequest, GetGroupActionsResponse, GetGroupInfoRequest, GetGroupInfoResponse, GetGroupInfosRequest, GetGroupInfosResponse, GetIdentitiesBalancesRequest, GetIdentitiesBalancesResponse, GetIdentitiesContractKeysRequest, GetIdentitiesContractKeysResponse, GetIdentitiesTokenBalancesRequest, GetIdentitiesTokenBalancesResponse, GetIdentitiesTokenInfosRequest, GetIdentitiesTokenInfosResponse, GetIdentityBalanceAndRevisionRequest, GetIdentityBalanceAndRevisionResponse, GetIdentityBalanceRequest, GetIdentityBalanceResponse, GetIdentityByNonUniquePublicKeyHashRequest, GetIdentityByNonUniquePublicKeyHashResponse, GetIdentityByPublicKeyHashRequest, GetIdentityByPublicKeyHashResponse, GetIdentityContractNonceRequest, GetIdentityContractNonceResponse, GetIdentityKeysRequest, GetIdentityKeysResponse, GetIdentityNonceRequest, GetIdentityNonceResponse, GetIdentityRequest, GetIdentityResponse, GetIdentityTokenBalancesRequest, GetIdentityTokenBalancesResponse, GetIdentityTokenInfosRequest, GetIdentityTokenInfosResponse, GetPathElementsRequest, GetPathElementsResponse, GetPrefundedSpecializedBalanceRequest, GetPrefundedSpecializedBalanceResponse, GetProofsRequest, GetProofsResponse, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, GetStatusRequest, GetStatusResponse, GetTokenPreProgrammedDistributionsRequest, GetTokenPreProgrammedDistributionsResponse, GetTokenStatusesRequest, GetTokenStatusesResponse, GetTokenTotalSupplyRequest, GetTokenTotalSupplyResponse, GetTotalCreditsInPlatformRequest, GetTotalCreditsInPlatformResponse, GetVotePollsByEndDateRequest, GetVotePollsByEndDateResponse, WaitForStateTransitionResultRequest, WaitForStateTransitionResultResponse}; use dapi_grpc::tonic::{Code, Request, Response, Status}; use dpp::version::PlatformVersion; use std::fmt::Debug; @@ -411,6 +378,15 @@ impl PlatformService for QueryService { .await } + async fn get_identity_by_non_unique_public_key_hash(&self, request: Request) -> Result, Status> { + self.handle_blocking_query( + request, + Platform::::query_identity_by_non_unique_public_key_hash, + "get_identity_by_non_unique_public_key_hash", + ) + .await + } + async fn wait_for_state_transition_result( &self, _request: Request, diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index 4a4103c4dbc..5e0aaba3d85 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -266,7 +266,7 @@ impl QueryStrategy { let (proof_root_hash, identity): ( RootHash, Option, - ) = Drive::verify_full_identity_by_public_key_hash( + ) = Drive::verify_full_identity_by_unique_public_key_hash( &proof.grovedb_proof, key_hash, platform_version, diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index 6399a3e691d..50e232de483 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -325,7 +325,7 @@ impl FromProof for Identity { }; // Extract content from proof and verify Drive/GroveDB proofs - let (root_hash, maybe_identity) = Drive::verify_full_identity_by_public_key_hash( + let (root_hash, maybe_identity) = Drive::verify_full_identity_by_unique_public_key_hash( &proof.grovedb_proof, public_key_hash, platform_version, diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs new file mode 100644 index 00000000000..58438b01e71 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs @@ -0,0 +1,53 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::{drive::DriveError, Error}; +use dpp::identity::Identity; + +use dpp::version::PlatformVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Fetches an identity with all its related information from storage based on a non unique public key hash. + /// + /// This function leverages the versioning system to direct the fetch operation to the appropriate handler based on the `DriveVersion` provided. + /// + /// # Arguments + /// + /// * `public_key_hash` - A non-unique public key hash corresponding to the identity to be fetched. + /// * `after` - An identity ID after which we want to get back our identity. Basically "don't get back this identity, get the next one" + /// * `transaction` - Transaction arguments. + /// * `drive_version` - A reference to the drive version. + /// + /// # Returns + /// + /// Returns a `Result` containing an `Option` of the `Identity` if it exists, otherwise an `Error` if the fetch operation fails or the version is not supported. + pub fn fetch_full_identity_by_non_unique_public_key_hash( + &self, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .identity + .fetch + .public_key_hashes + .fetch_full_identity_by_non_unique_public_key_hash + { + 0 => self.fetch_full_identity_by_non_unique_public_key_hash_v0( + public_key_hash, + after, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "fetch_full_identity_by_non_unique_public_key_hash".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs new file mode 100644 index 00000000000..44fb166d486 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs @@ -0,0 +1,53 @@ +use crate::drive::Drive; + +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; + +use dpp::identity::Identity; +use dpp::version::PlatformVersion; + +use grovedb::TransactionArg; + +impl Drive { + /// Fetches an identity with all its information from storage. + pub(super) fn fetch_full_identity_by_non_unique_public_key_hash_v0( + &self, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut drive_operations: Vec = vec![]; + self.fetch_full_identity_by_non_unique_public_key_hash_operations_v0( + public_key_hash, + after, + transaction, + &mut drive_operations, + platform_version, + ) + } + + /// Given an identity, fetches the identity with its flags from storage. + pub(super) fn fetch_full_identity_by_non_unique_public_key_hash_operations_v0( + &self, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let identity_ids = self.fetch_identity_ids_by_non_unique_public_key_hash_operations( + public_key_hash, + Some(1), + after, + transaction, + drive_operations, + platform_version, + )?; + if let Some(identity_id) = identity_ids.first() { + self.fetch_full_identity(*identity_id, transaction, platform_version) + } else { + Ok(None) + } + } +} diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs index 9c444e59731..892d91c7bf5 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs @@ -2,8 +2,9 @@ mod v0; use crate::drive::Drive; use crate::error::{drive::DriveError, Error}; -use dpp::version::drive_versions::DriveVersion; use grovedb::TransactionArg; +use platform_version::version::PlatformVersion; +use crate::fees::op::LowLevelDriveOperation; impl Drive { /// Fetches identity ids from storage based on a non-unique public key hash. @@ -13,8 +14,9 @@ impl Drive { /// # Arguments /// /// * `public_key_hash` - A non-unique public key hash corresponding to the identity ids to be fetched. + /// * `limit` - An optional limit. /// * `transaction` - Transaction arguments. - /// * `drive_version` - A reference to the drive version. + /// * `platform_version` - A reference to the platform version. /// /// # Returns /// @@ -22,10 +24,12 @@ impl Drive { pub fn fetch_identity_ids_by_non_unique_public_key_hash( &self, public_key_hash: [u8; 20], + limit: Option, + after: Option<[u8;32]>, transaction: TransactionArg, - drive_version: &DriveVersion, + platform_version: &PlatformVersion, ) -> Result, Error> { - match drive_version + match platform_version.drive .methods .identity .fetch @@ -34,8 +38,10 @@ impl Drive { { 0 => self.fetch_identity_ids_by_non_unique_public_key_hash_v0( public_key_hash, + limit, + after, transaction, - drive_version, + platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "fetch_identity_ids_by_non_unique_public_key_hash".to_string(), @@ -44,4 +50,36 @@ impl Drive { })), } } + + pub(crate) fn fetch_identity_ids_by_non_unique_public_key_hash_operations( + &self, + public_key_hash: [u8; 20], + limit: Option, + after: Option<[u8;32]>, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version.drive + .methods + .identity + .fetch + .public_key_hashes + .fetch_identity_ids_by_non_unique_public_key_hash + { + 0 => self.fetch_identity_ids_by_non_unique_public_key_hash_operations_v0( + public_key_hash, + limit, + after, + transaction, + drive_operations, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "fetch_identity_ids_by_non_unique_public_key_hash_operations".to_string(), + known_versions: vec![0], + received: version, + })), + } + } } diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs index ee462d63281..1eb970654f7 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs @@ -6,48 +6,62 @@ use crate::query::QueryItem; use grovedb::query_result_type::QueryResultType; -use dpp::version::drive_versions::DriveVersion; - use grovedb::{PathQuery, TransactionArg}; use std::ops::RangeFull; +use platform_version::version::PlatformVersion; impl Drive { /// Fetches identity ids from storage. pub(super) fn fetch_identity_ids_by_non_unique_public_key_hash_v0( &self, public_key_hash: [u8; 20], + limit: Option, + after: Option<[u8;32]>, transaction: TransactionArg, - drive_version: &DriveVersion, + platform_version: &PlatformVersion, ) -> Result, Error> { let mut drive_operations: Vec = vec![]; self.fetch_identity_ids_by_non_unique_public_key_hash_operations_v0( public_key_hash, + limit, + after, transaction, &mut drive_operations, - drive_version, + platform_version, ) } - /// Gets identity ids from non unique public key hashes. + /// Gets identity ids from non-unique public key hashes. pub(super) fn fetch_identity_ids_by_non_unique_public_key_hash_operations_v0( &self, public_key_hash: [u8; 20], + limit: Option, + after: Option<[u8;32]>, transaction: TransactionArg, drive_operations: &mut Vec, - drive_version: &DriveVersion, + platform_version: &PlatformVersion, ) -> Result, Error> { let non_unique_key_hashes = non_unique_key_hashes_sub_tree_path_vec(public_key_hash); - let path_query = PathQuery::new_single_query_item( - non_unique_key_hashes, - QueryItem::RangeFull(RangeFull), - ); + let mut path_query = if let Some(after) = after { + PathQuery::new_single_query_item( + non_unique_key_hashes, + QueryItem::RangeAfter(after.to_vec()..), + ) + } else { + PathQuery::new_single_query_item( + non_unique_key_hashes, + QueryItem::RangeFull(RangeFull), + ) + }; + path_query.query.limit = limit; + let (results, _) = self.grove_get_path_query( &path_query, transaction, QueryResultType::QueryKeyElementPairResultType, drive_operations, - drive_version, + &platform_version.drive, )?; results .to_keys() diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs index 859982396ab..849fdbe8626 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs @@ -7,6 +7,7 @@ mod has_any_of_unique_public_key_hashes; mod has_non_unique_public_key_hash; mod has_non_unique_public_key_hash_already_for_identity; mod has_unique_public_key_hash; +mod fetch_full_identity_by_non_unique_public_key_hash; #[cfg(feature = "server")] #[cfg(test)] @@ -23,7 +24,6 @@ mod tests { fn test_fetch_all_keys_on_identity() { let drive = setup_drive(None, None); let platform_version = PlatformVersion::latest(); - let drive_version = &platform_version.drive; let transaction = drive.grove.start_transaction(); @@ -71,8 +71,10 @@ mod tests { let identity_ids = drive .fetch_identity_ids_by_non_unique_public_key_hash( hash, + None, + None, Some(&transaction), - &drive_version, + platform_version, ) .expect("expected to get identity ids"); assert!(identity_ids.contains(&identity.id().to_buffer())); diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs index b095b6bf427..01678cef1eb 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs @@ -5,3 +5,4 @@ mod prove_full_identity_by_unique_public_key_hash; mod prove_identities_contract_keys; mod prove_identity_id_by_unique_public_key_hash; mod prove_identity_ids_by_unique_public_key_hashes; +mod prove_full_identity_by_non_unique_public_key_hash; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs new file mode 100644 index 00000000000..5703fc6920b --- /dev/null +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs @@ -0,0 +1,52 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; + +use dpp::version::PlatformVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Fetches an identity with all its information from storage. + /// + /// This function uses the versioning system to call the appropriate handler based on the provided `DriveVersion`. + /// + /// # Arguments + /// + /// * `public_key_hash` - The public key hash for which to fetch the identity. + /// * `after` - An identity ID after which we want to get back our identity. Basically "don't get back this identity, get the next one" + /// * `transaction` - Transaction arguments. + /// * `drive_version` - A reference to the drive version. + /// + /// # Returns + /// + /// Returns a `Result` containing a vector of bytes representing the proved identity, otherwise an `Error` if the operation fails or the version is not supported. + pub fn prove_full_identity_by_non_unique_public_key_hash( + &self, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .identity + .prove + .prove_full_identity_by_non_unique_public_key_hash + { + 0 => self.prove_full_identity_by_non_unique_public_key_hash_v0( + public_key_hash, + after, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "prove_full_identity_by_non_unique_public_key_hash".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs new file mode 100644 index 00000000000..7231d8bee9b --- /dev/null +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs @@ -0,0 +1,234 @@ +use crate::drive::Drive; + +use crate::error::Error; + +use dpp::version::PlatformVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Fetches an identity with all its information from storage. + pub(super) fn prove_full_identity_by_non_unique_public_key_hash_v0( + &self, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let identity_ids = self.fetch_identity_ids_by_non_unique_public_key_hash_operations( + public_key_hash, + Some(1), + after, + transaction, + &mut vec![], + platform_version, + )?; + if let Some(identity_id) = identity_ids.first() { + let query = Self::full_identity_with_non_unique_public_key_hash_query( + public_key_hash, + *identity_id, + after, + &platform_version.drive.grove_version, + )?; + self.grove_get_proved_path_query( + &query, + transaction, + &mut vec![], + &platform_version.drive, + ) + } else { + // We only prove the absence of the public key hash + let query = Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); + self.grove_get_proved_path_query( + &query, + transaction, + &mut vec![], + &platform_version.drive, + ) + } + } +} + +#[cfg(test)] +mod tests { + use rand::prelude::StdRng; + use rand::SeedableRng; + use super::*; + use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + use dpp::block::block_info::BlockInfo; + use dpp::identity::accessors::IdentityGettersV0; + use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; + use dpp::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMethodsV0; + use dpp::identity::{Identity, IdentityPublicKey, KeyType}; + use dpp::version::PlatformVersion; + + #[test] + fn should_prove_a_single_identity() { + let drive = setup_drive_with_initial_state_structure(None); + + let platform_version = PlatformVersion::latest(); + + let identity = Identity::random_identity(3, Some(14), platform_version) + .expect("expected a random identity"); + + drive + .add_new_identity( + identity.clone(), + false, + &BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to add an identity"); + + let first_key_hash = identity + .public_keys() + .values() + .find(|public_key| public_key.key_type().is_unique_key_type()) + .expect("expected a unique key") + .public_key_hash() + .expect("expected to hash data"); + + let proof = drive + .prove_full_identity_by_unique_public_key_hash(first_key_hash, None, platform_version) + .expect("should not error when proving an identity"); + + let (_, proved_identity) = Drive::verify_full_identity_by_unique_public_key_hash( + proof.as_slice(), + first_key_hash, + platform_version, + ) + .expect("expect that this be verified"); + + assert_eq!(proved_identity, Some(identity)); + } + + #[test] + fn should_prove_a_single_identity_with_non_unique_key() { + let drive = setup_drive_with_initial_state_structure(None); + + let platform_version = PlatformVersion::latest(); + + let identity = Identity::random_identity(3, Some(14), platform_version) + .expect("expected a random identity"); + + drive + .add_new_identity( + identity.clone(), + false, + &BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to add an identity"); + + let first_key_hash = identity + .public_keys() + .values() + .find(|public_key| !public_key.key_type().is_unique_key_type()) + .expect("expected a unique key") + .public_key_hash() + .expect("expected to hash data"); + + let proof = drive + .prove_full_identity_by_non_unique_public_key_hash(first_key_hash, None, None, platform_version) + .expect("should not error when proving an identity"); + + let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( + proof.as_slice(), + first_key_hash, + None, + platform_version, + ) + .expect("expect that this be verified"); + + assert_eq!(proved_identity, Some(identity)); + } + + #[test] + fn should_prove_a_single_identity_with_non_unique_key_when_two_have_same_key() { + let drive = setup_drive_with_initial_state_structure(None); + + let platform_version = PlatformVersion::latest(); + + let mut identity_1 = Identity::random_identity(3, Some(14), platform_version) + .expect("expected a random identity"); + + let mut identity_2 = Identity::random_identity(3, Some(15), platform_version) + .expect("expected a random identity"); + + let mut rng = StdRng::seed_from_u64(506); + + let key = IdentityPublicKey::random_voting_key_with_rng(3, &mut rng, platform_version).expect("expected key").0; + + identity_1.add_public_key(key.clone()); + identity_2.add_public_key(key.clone()); + + drive + .add_new_identity( + identity_1.clone(), + false, + &BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to add an identity"); + + drive + .add_new_identity( + identity_2.clone(), + false, + &BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to add an identity"); + + let key_hash = key.public_key_hash().expect("expected key hash"); + + let proof = drive + .prove_full_identity_by_non_unique_public_key_hash(key_hash, None, None, platform_version) + .expect("should not error when proving an identity"); + + let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( + proof.as_slice(), + key_hash, + None, + platform_version, + ) + .expect("expect that this be verified"); + + assert_eq!(proved_identity, Some(identity_1.clone())); + + let proof = drive + .prove_full_identity_by_non_unique_public_key_hash(key_hash, Some(identity_1.id().to_buffer()), None, platform_version) + .expect("should not error when proving an identity"); + + let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( + proof.as_slice(), + key_hash, + Some(identity_1.id().to_buffer()), + platform_version, + ) + .expect("expect that this be verified"); + + assert_eq!(proved_identity, Some(identity_2.clone())); + + let proof = drive + .prove_full_identity_by_non_unique_public_key_hash(key_hash, Some(identity_2.id().to_buffer()), None, platform_version) + .expect("should not error when proving an identity"); + + let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( + proof.as_slice(), + key_hash, + Some(identity_2.id().to_buffer()), + platform_version, + ) + .expect("expect that this be verified"); + + assert_eq!(proved_identity, None); + } +} diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs index f474fa52315..085920640ba 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs @@ -87,7 +87,7 @@ mod tests { .prove_full_identity_by_unique_public_key_hash(first_key_hash, None, platform_version) .expect("should not error when proving an identity"); - let (_, proved_identity) = Drive::verify_full_identity_by_public_key_hash( + let (_, proved_identity) = Drive::verify_full_identity_by_unique_public_key_hash( proof.as_slice(), first_key_hash, platform_version, diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs index 8900c2e2dcc..83af15538f1 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs @@ -65,7 +65,7 @@ mod tests { ) .expect("should not error when proving an identity"); - let (_, proved_identity_id) = Drive::verify_identity_id_by_public_key_hash( + let (_, proved_identity_id) = Drive::verify_identity_id_by_unique_public_key_hash( proof.as_slice(), false, first_key_hash, diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs index 1b4636e6b5a..d9c54243db5 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs @@ -89,7 +89,7 @@ mod tests { .expect("should not error when proving an identity"); let (_, proved_identity_id): ([u8; 32], BTreeMap<[u8; 20], Option<[u8; 32]>>) = - Drive::verify_identity_ids_by_public_key_hashes( + Drive::verify_identity_ids_by_unique_public_key_hashes( proof.as_slice(), false, &key_hashes, diff --git a/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs b/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs index f7832d2274f..685b7353c46 100644 --- a/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs @@ -1,6 +1,6 @@ use crate::drive::balances::balance_path_vec; use crate::drive::identity::key::fetch::IdentityKeysRequest; -use crate::drive::{identity_tree_path_vec, unique_key_hashes_tree_path_vec, Drive}; +use crate::drive::{identity_tree_path_vec, non_unique_key_hashes_tree_path, non_unique_key_hashes_tree_path_vec, unique_key_hashes_tree_path_vec, Drive}; use std::ops::RangeFull; use crate::error::Error; @@ -90,6 +90,22 @@ impl Drive { PathQuery::new_single_key(unique_key_hashes, public_key_hash.to_vec()) } + /// The query for proving an identity id from a non-unique public key hash. + /// This should be used for absence proofs + pub fn identity_id_by_non_unique_public_key_hash_query(public_key_hash: [u8; 20], after: Option<[u8;32]>) -> PathQuery { + let non_unique_key_hashes = non_unique_key_hashes_tree_path_vec(); + let mut query = Query::new_single_key(public_key_hash.to_vec()); + let sub_query = if let Some(after) = after { + Query::new_single_query_item(QueryItem::RangeFrom( + after.to_vec().., + )) + } else { + Query::new_range_full() + }; + query.set_subquery(sub_query); + PathQuery::new(non_unique_key_hashes, SizedQuery::new(query, None, None)) + } + /// The query for proving identity ids from a vector of public key hashes. pub fn identity_ids_by_unique_public_key_hash_query( public_key_hashes: &[[u8; 20]], @@ -213,6 +229,23 @@ impl Drive { .map_err(Error::GroveDB) } + /// This query gets the full identity and the public key hash + pub fn full_identity_with_non_unique_public_key_hash_query( + public_key_hash: [u8; 20], + identity_id: [u8; 32], + after: Option<[u8;32]>, + grove_version: &GroveVersion, + ) -> Result { + let full_identity_query = Self::full_identity_query(&identity_id, grove_version)?; + let identity_id_by_public_key_hash_query = + Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); + PathQuery::merge( + vec![&full_identity_query, &identity_id_by_public_key_hash_query], + grove_version, + ) + .map_err(Error::GroveDB) + } + /// The query full identities with key hashes too pub fn full_identities_with_keys_hashes_query( identity_ids: &[[u8; 32]], diff --git a/packages/rs-drive/src/verify/identity/mod.rs b/packages/rs-drive/src/verify/identity/mod.rs index dd24b00f678..9e0482bc79e 100644 --- a/packages/rs-drive/src/verify/identity/mod.rs +++ b/packages/rs-drive/src/verify/identity/mod.rs @@ -1,13 +1,15 @@ mod verify_full_identities_by_public_key_hashes; mod verify_full_identity_by_identity_id; -mod verify_full_identity_by_public_key_hash; +mod verify_full_identity_by_unique_public_key_hash; +mod verify_full_identity_by_non_unique_public_key_hash; mod verify_identities_contract_keys; mod verify_identity_balance_and_revision_for_identity_id; mod verify_identity_balance_for_identity_id; mod verify_identity_balances_for_identity_ids; mod verify_identity_contract_nonce; -mod verify_identity_id_by_public_key_hash; -mod verify_identity_ids_by_public_key_hashes; +mod verify_identity_id_by_unique_public_key_hash; +mod verify_identity_ids_by_unique_public_key_hashes; mod verify_identity_keys_by_identity_id; mod verify_identity_nonce; mod verify_identity_revision_for_identity_id; +mod verify_identity_id_by_non_unique_public_key_hash; diff --git a/packages/rs-drive/src/verify/identity/verify_full_identities_by_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identities_by_public_key_hashes/v0/mod.rs index 7c1f0545d05..43ce89e6d00 100644 --- a/packages/rs-drive/src/verify/identity/verify_full_identities_by_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_full_identities_by_public_key_hashes/v0/mod.rs @@ -48,7 +48,7 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result<(RootHash, T), Error> { let (root_hash, identity_ids_by_key_hashes) = - Self::verify_identity_ids_by_public_key_hashes::>( + Self::verify_identity_ids_by_unique_public_key_hashes::>( proof, true, public_key_hashes, diff --git a/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs new file mode 100644 index 00000000000..b290bec46fe --- /dev/null +++ b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs @@ -0,0 +1,66 @@ +mod v0; + +use crate::drive::Drive; + +use crate::error::drive::DriveError; + +use crate::error::Error; + +use crate::verify::RootHash; + +pub use dpp::prelude::Identity; + +use dpp::version::PlatformVersion; + +impl Drive { + /// Verifies the full identity of a user by their public key hash. + /// + /// # Parameters + /// + /// - `proof`: A byte slice representing the proof of authentication from the user. + /// - `public_key_hash`: A 20-byte array representing the hash of the public key of the user. + /// - `after`: A 32 byte array representing an identity after which we want to get the identity. + /// - `platform_version`: The platform version against which to verify the identity. + /// + /// # Returns + /// + /// If the verification is successful, it returns a `Result` with a tuple of `RootHash` and + /// an `Option` of `Identity`. The `RootHash` represents the root hash of GroveDB, and the + /// `Option` represents the full identity of the user if it exists. + /// + /// # Errors + /// + /// Returns an `Error` if: + /// + /// - The proof of authentication is not valid. + /// - The public key hash does not correspond to a valid identity ID. + /// - The identity ID does not correspond to a valid full identity. + /// - An unknown or unsupported platform version is provided. + /// + pub fn verify_full_identity_by_non_unique_public_key_hash( + proof: &[u8], + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Option), Error> { + match platform_version + .drive + .methods + .verify + .identity + .verify_full_identity_by_non_unique_public_key_hash + { + 0 => Self::verify_full_identity_by_non_unique_public_key_hash_v0( + proof, + public_key_hash, + after, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "verify_full_identity_by_non_unique_public_key_hash".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs new file mode 100644 index 00000000000..ee3024d1a7a --- /dev/null +++ b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs @@ -0,0 +1,68 @@ +use crate::drive::Drive; + +use crate::error::Error; + +use crate::verify::RootHash; + +pub use dpp::prelude::Identity; + +use dpp::version::PlatformVersion; + +impl Drive { + /// Verifies the full identity of a user by their public key hash. + /// + /// This function takes a byte slice `proof` and a 20-byte array `public_key_hash` as arguments, + /// then it verifies the identity of the user with the given public key hash. + /// + /// The `proof` should contain the proof of authentication from the user. + /// The `public_key_hash` should contain the hash of the public key of the user. + /// + /// The function first verifies the identity ID associated with the given public key hash + /// by calling `verify_identity_id_by_non_unique_public_key_hash()`. It then uses this identity ID to verify + /// the full identity by calling `verify_full_identity_by_identity_id()`. + /// + /// # Returns + /// + /// If the verification is successful, it returns a `Result` with a tuple of `RootHash` and + /// an `Option` of `Identity`. The `RootHash` represents the root hash of GroveDB, and the + /// `Option` represents the full identity of the user if it exists. + /// + /// If the verification fails at any point, it will return an `Error`. + /// + /// # Errors + /// + /// This function will return an `Error` if: + /// + /// * The proof of authentication is not valid. + /// * The public key hash does not correspond to a valid identity ID. + /// * The identity ID does not correspond to a valid full identity. + /// + #[inline(always)] + pub(super) fn verify_full_identity_by_non_unique_public_key_hash_v0( + proof: &[u8], + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Option), Error> { + let (root_hash, identity_id) = Self::verify_identity_id_by_non_unique_public_key_hash( + proof, + true, + public_key_hash, + after, + platform_version, + )?; + let maybe_identity = identity_id + .map(|identity_id| { + Self::verify_full_identity_by_identity_id( + proof, + true, + identity_id, + platform_version, + ) + .map(|(_, maybe_identity)| maybe_identity) + }) + .transpose()? + .flatten(); + Ok((root_hash, maybe_identity)) + } +} diff --git a/packages/rs-drive/src/verify/identity/verify_full_identity_by_public_key_hash/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identity_by_unique_public_key_hash/mod.rs similarity index 89% rename from packages/rs-drive/src/verify/identity/verify_full_identity_by_public_key_hash/mod.rs rename to packages/rs-drive/src/verify/identity/verify_full_identity_by_unique_public_key_hash/mod.rs index 6ce7cc6f263..17cd33c1995 100644 --- a/packages/rs-drive/src/verify/identity/verify_full_identity_by_public_key_hash/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_full_identity_by_unique_public_key_hash/mod.rs @@ -36,7 +36,7 @@ impl Drive { /// - The identity ID does not correspond to a valid full identity. /// - An unknown or unsupported platform version is provided. /// - pub fn verify_full_identity_by_public_key_hash( + pub fn verify_full_identity_by_unique_public_key_hash( proof: &[u8], public_key_hash: [u8; 20], platform_version: &PlatformVersion, @@ -48,13 +48,13 @@ impl Drive { .identity .verify_full_identity_by_public_key_hash { - 0 => Self::verify_full_identity_by_public_key_hash_v0( + 0 => Self::verify_full_identity_by_unique_public_key_hash_v0( proof, public_key_hash, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "verify_full_identity_by_public_key_hash".to_string(), + method: "verify_full_identity_by_unique_public_key_hash".to_string(), known_versions: vec![0], received: version, })), diff --git a/packages/rs-drive/src/verify/identity/verify_full_identity_by_public_key_hash/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identity_by_unique_public_key_hash/v0/mod.rs similarity index 96% rename from packages/rs-drive/src/verify/identity/verify_full_identity_by_public_key_hash/v0/mod.rs rename to packages/rs-drive/src/verify/identity/verify_full_identity_by_unique_public_key_hash/v0/mod.rs index e481343470a..88fe2894242 100644 --- a/packages/rs-drive/src/verify/identity/verify_full_identity_by_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_full_identity_by_unique_public_key_hash/v0/mod.rs @@ -38,12 +38,12 @@ impl Drive { /// * The identity ID does not correspond to a valid full identity. /// #[inline(always)] - pub(super) fn verify_full_identity_by_public_key_hash_v0( + pub(super) fn verify_full_identity_by_unique_public_key_hash_v0( proof: &[u8], public_key_hash: [u8; 20], platform_version: &PlatformVersion, ) -> Result<(RootHash, Option), Error> { - let (root_hash, identity_id) = Self::verify_identity_id_by_public_key_hash( + let (root_hash, identity_id) = Self::verify_identity_id_by_unique_public_key_hash( proof, true, public_key_hash, diff --git a/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs new file mode 100644 index 00000000000..5cf78fb3964 --- /dev/null +++ b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs @@ -0,0 +1,65 @@ +mod v0; + +use crate::drive::Drive; + +use crate::error::drive::DriveError; + +use crate::error::Error; + +use crate::verify::RootHash; + +use dpp::version::PlatformVersion; + +impl Drive { + /// Verifies the identity ID of a user by their public key hash. + /// + /// # Parameters + /// + /// - `proof`: A byte slice representing the proof of authentication from the user. + /// - `is_proof_subset`: A boolean indicating whether the proof is a subset. + /// - `public_key_hash`: A 20-byte array representing the hash of the public key of the user. + /// - `after`: A 32 byte array representing an identity after which we want to get the identity id. + /// - `platform_version`: The platform version against which to verify the identity ID. + /// + /// # Returns + /// + /// If the verification is successful, it returns a `Result` with a tuple of `RootHash` and + /// an `Option` of a 32-byte array. The `RootHash` represents the root hash of GroveDB, + /// and the `Option<[u8; 32]>` represents the identity ID of the user if it exists. + /// + /// # Errors + /// + /// Returns an `Error` if: + /// + /// - An unknown or unsupported platform version is provided. + /// - Any other error as documented in the specific versioned function. + /// + pub fn verify_identity_id_by_non_unique_public_key_hash( + proof: &[u8], + is_proof_subset: bool, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Option<[u8; 32]>), Error> { + match platform_version + .drive + .methods + .verify + .identity + .verify_identity_id_by_non_unique_public_key_hash + { + 0 => Self::verify_identity_id_by_non_unique_public_key_hash_v0( + proof, + is_proof_subset, + public_key_hash, + after, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "verify_identity_id_by_non_unique_public_key_hash".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs new file mode 100644 index 00000000000..01429e1e628 --- /dev/null +++ b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs @@ -0,0 +1,78 @@ +use crate::drive::{non_unique_key_hashes_sub_tree_path_vec, Drive}; + +use crate::error::proof::ProofError; +use crate::error::Error; + +use crate::verify::RootHash; + +use grovedb::GroveDb; +use platform_version::version::PlatformVersion; + +impl Drive { + /// Verifies the identity ID of a user by their public key hash. + /// + /// # Parameters + /// + /// - `proof`: A byte slice representing the proof of authentication from the user. + /// - `is_proof_subset`: A boolean indicating whether the proof is a subset. + /// - `public_key_hash`: A 20-byte array representing the hash of the public key of the user. + /// - `after`: A 32 byte array representing an identity after which we want to get the identity id. + /// + /// # Returns + /// + /// If the verification is successful, it returns a `Result` with a tuple of `RootHash` and + /// an `Option` of a 32-byte array. The `RootHash` represents the root hash of GroveDB, + /// and the `Option<[u8; 32]>` represents the identity ID of the user if it exists. + /// + /// # Errors + /// + /// Returns an `Error` if: + /// + /// - The proof of authentication is not valid. + /// - The public key hash does not correspond to a valid identity ID. + /// - The proved key value is not for the correct path or key in unique key hashes. + /// - More than one identity ID is found. + /// + #[inline(always)] + pub(super) fn verify_identity_id_by_non_unique_public_key_hash_v0( + proof: &[u8], + is_proof_subset: bool, + public_key_hash: [u8; 20], + after: Option<[u8;32]>, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Option<[u8; 32]>), Error> { + let mut path_query = Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); + path_query.query.limit = Some(1); + let (root_hash, mut proved_key_values) = if is_proof_subset { + GroveDb::verify_subset_query( + proof, + &path_query, + &platform_version.drive.grove_version, + )? + } else { + GroveDb::verify_query( + proof, + &path_query, + &platform_version.drive.grove_version, + )? + }; + + if proved_key_values.len() == 1 { + let (path, key, _) = proved_key_values.remove(0); + if path != non_unique_key_hashes_sub_tree_path_vec(public_key_hash) { + return Err(Error::Proof(ProofError::CorruptedProof( + "we did not get back an element for the correct path in non unique key hashes" + .to_string(), + ))); + } + let identity_id = key + .try_into() + .map_err(|_| { + Error::Proof(ProofError::IncorrectValueSize("value size is incorrect")) + })?; + Ok((root_hash, Some(identity_id))) + } else { + Ok((root_hash, None)) + } + } +} diff --git a/packages/rs-drive/src/verify/identity/verify_identity_id_by_public_key_hash/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_id_by_unique_public_key_hash/mod.rs similarity index 86% rename from packages/rs-drive/src/verify/identity/verify_identity_id_by_public_key_hash/mod.rs rename to packages/rs-drive/src/verify/identity/verify_identity_id_by_unique_public_key_hash/mod.rs index 75182ffeefc..4422e600e01 100644 --- a/packages/rs-drive/src/verify/identity/verify_identity_id_by_public_key_hash/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_identity_id_by_unique_public_key_hash/mod.rs @@ -33,7 +33,7 @@ impl Drive { /// - An unknown or unsupported platform version is provided. /// - Any other error as documented in the specific versioned function. /// - pub fn verify_identity_id_by_public_key_hash( + pub fn verify_identity_id_by_unique_public_key_hash( proof: &[u8], is_proof_subset: bool, public_key_hash: [u8; 20], @@ -44,16 +44,16 @@ impl Drive { .methods .verify .identity - .verify_identity_id_by_public_key_hash + .verify_identity_id_by_unique_public_key_hash { - 0 => Self::verify_identity_id_by_public_key_hash_v0( + 0 => Self::verify_identity_id_by_unique_public_key_hash_v0( proof, is_proof_subset, public_key_hash, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "verify_identity_id_by_public_key_hash".to_string(), + method: "verify_identity_id_by_unique_public_key_hash".to_string(), known_versions: vec![0], received: version, })), diff --git a/packages/rs-drive/src/verify/identity/verify_identity_id_by_public_key_hash/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_id_by_unique_public_key_hash/v0/mod.rs similarity index 98% rename from packages/rs-drive/src/verify/identity/verify_identity_id_by_public_key_hash/v0/mod.rs rename to packages/rs-drive/src/verify/identity/verify_identity_id_by_unique_public_key_hash/v0/mod.rs index ceb8ae05b07..cccc1aa0f15 100644 --- a/packages/rs-drive/src/verify/identity/verify_identity_id_by_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_identity_id_by_unique_public_key_hash/v0/mod.rs @@ -33,7 +33,7 @@ impl Drive { /// - More than one identity ID is found. /// #[inline(always)] - pub(super) fn verify_identity_id_by_public_key_hash_v0( + pub(super) fn verify_identity_id_by_unique_public_key_hash_v0( proof: &[u8], is_proof_subset: bool, public_key_hash: [u8; 20], diff --git a/packages/rs-drive/src/verify/identity/verify_identity_ids_by_public_key_hashes/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_ids_by_unique_public_key_hashes/mod.rs similarity index 87% rename from packages/rs-drive/src/verify/identity/verify_identity_ids_by_public_key_hashes/mod.rs rename to packages/rs-drive/src/verify/identity/verify_identity_ids_by_unique_public_key_hashes/mod.rs index 20a9d98c3d8..6d1f70f8a04 100644 --- a/packages/rs-drive/src/verify/identity/verify_identity_ids_by_public_key_hashes/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_identity_ids_by_unique_public_key_hashes/mod.rs @@ -36,7 +36,7 @@ impl Drive { /// - An unknown or unsupported platform version is provided. /// - Any other error as documented in the specific versioned function. /// - pub fn verify_identity_ids_by_public_key_hashes< + pub fn verify_identity_ids_by_unique_public_key_hashes< T: FromIterator<([u8; 20], Option<[u8; 32]>)>, >( proof: &[u8], @@ -49,16 +49,16 @@ impl Drive { .methods .verify .identity - .verify_identity_ids_by_public_key_hashes + .verify_identity_ids_by_unique_public_key_hashes { - 0 => Self::verify_identity_ids_by_public_key_hashes_v0( + 0 => Self::verify_identity_ids_by_unique_public_key_hashes_v0( proof, is_proof_subset, public_key_hashes, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "verify_identity_ids_by_public_key_hashes".to_string(), + method: "verify_identity_ids_by_unique_public_key_hashes".to_string(), known_versions: vec![0], received: version, })), diff --git a/packages/rs-drive/src/verify/identity/verify_identity_ids_by_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_ids_by_unique_public_key_hashes/v0/mod.rs similarity index 98% rename from packages/rs-drive/src/verify/identity/verify_identity_ids_by_public_key_hashes/v0/mod.rs rename to packages/rs-drive/src/verify/identity/verify_identity_ids_by_unique_public_key_hashes/v0/mod.rs index 6d1c6dc7d85..90beab8eaf3 100644 --- a/packages/rs-drive/src/verify/identity/verify_identity_ids_by_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_identity_ids_by_unique_public_key_hashes/v0/mod.rs @@ -37,7 +37,7 @@ impl Drive { /// - The number of proved key values does not match the number of public key hashes provided. /// - The value size of the identity ID is incorrect. /// - pub(crate) fn verify_identity_ids_by_public_key_hashes_v0< + pub(crate) fn verify_identity_ids_by_unique_public_key_hashes_v0< T: FromIterator<([u8; 20], Option<[u8; 32]>)>, >( proof: &[u8], 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 7a5d65bd3ea..ac3412fd85e 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 @@ -52,7 +52,7 @@ pub struct DriveAbciQueryIdentityVersions { pub balance: FeatureVersionBounds, pub identities_balances: FeatureVersionBounds, pub balance_and_revision: FeatureVersionBounds, - pub identity_by_public_key_hash: FeatureVersionBounds, + pub identity_by_unique_public_key_hash: FeatureVersionBounds, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs index 494dfa6f097..829c9a218d2 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs @@ -67,7 +67,7 @@ pub const DRIVE_ABCI_QUERY_VERSIONS_V1: DriveAbciQueryVersions = DriveAbciQueryV max_version: 0, default_current_version: 0, }, - identity_by_public_key_hash: FeatureVersionBounds { + identity_by_unique_public_key_hash: FeatureVersionBounds { min_version: 0, max_version: 0, default_current_version: 0, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs index 7528ec11a40..6930d7e4930 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs @@ -94,6 +94,7 @@ pub struct DriveIdentityFetchPublicKeyHashesMethodVersions { pub has_non_unique_public_key_hash: FeatureVersion, pub has_non_unique_public_key_hash_already_for_identity: FeatureVersion, pub has_unique_public_key_hash: FeatureVersion, + pub fetch_full_identity_by_non_unique_public_key_hash: FeatureVersion, } #[derive(Clone, Debug, Default)] @@ -132,6 +133,7 @@ pub struct DriveIdentityProveMethodVersions { pub prove_full_identity_by_unique_public_key_hash: FeatureVersion, pub prove_identity_id_by_unique_public_key_hash: FeatureVersion, pub prove_identity_ids_by_unique_public_key_hashes: FeatureVersion, + pub prove_full_identity_by_non_unique_public_key_hash: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs index 3db719ae7fa..f3c1bedd59f 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs @@ -27,6 +27,7 @@ pub const DRIVE_IDENTITY_METHOD_VERSIONS_V1: DriveIdentityMethodVersions = has_non_unique_public_key_hash: 0, has_non_unique_public_key_hash_already_for_identity: 0, has_unique_public_key_hash: 0, + fetch_full_identity_by_non_unique_public_key_hash: 0, }, attributes: DriveIdentityFetchAttributesMethodVersions { revision: 0, @@ -58,6 +59,7 @@ pub const DRIVE_IDENTITY_METHOD_VERSIONS_V1: DriveIdentityMethodVersions = prove_full_identity_by_unique_public_key_hash: 0, prove_identity_id_by_unique_public_key_hash: 0, prove_identity_ids_by_unique_public_key_hashes: 0, + prove_full_identity_by_non_unique_public_key_hash: 0, }, keys: DriveIdentityKeysMethodVersions { fetch: DriveIdentityKeysFetchMethodVersions { diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs index f8082f48198..90cd83d5291 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs @@ -35,13 +35,15 @@ pub struct DriveVerifyIdentityMethodVersions { pub verify_full_identity_by_public_key_hash: FeatureVersion, pub verify_identity_balance_for_identity_id: FeatureVersion, pub verify_identity_balances_for_identity_ids: FeatureVersion, - pub verify_identity_id_by_public_key_hash: FeatureVersion, - pub verify_identity_ids_by_public_key_hashes: FeatureVersion, + pub verify_identity_id_by_unique_public_key_hash: FeatureVersion, + pub verify_identity_ids_by_unique_public_key_hashes: FeatureVersion, pub verify_identity_keys_by_identity_id: FeatureVersion, pub verify_identity_nonce: FeatureVersion, pub verify_identity_contract_nonce: FeatureVersion, pub verify_identities_contract_keys: FeatureVersion, pub verify_identity_revision_for_identity_id: FeatureVersion, + pub verify_full_identity_by_non_unique_public_key_hash: FeatureVersion, + pub verify_identity_id_by_non_unique_public_key_hash: FeatureVersion, } #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs index 666ab416ca7..a848e92c7dd 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs @@ -21,13 +21,15 @@ pub const DRIVE_VERIFY_METHOD_VERSIONS_V1: DriveVerifyMethodVersions = DriveVeri verify_full_identity_by_public_key_hash: 0, verify_identity_balance_for_identity_id: 0, verify_identity_balances_for_identity_ids: 0, - verify_identity_id_by_public_key_hash: 0, - verify_identity_ids_by_public_key_hashes: 0, + verify_identity_id_by_unique_public_key_hash: 0, + verify_identity_ids_by_unique_public_key_hashes: 0, verify_identity_keys_by_identity_id: 0, verify_identity_nonce: 0, verify_identity_contract_nonce: 0, verify_identities_contract_keys: 0, verify_identity_revision_for_identity_id: 0, + verify_full_identity_by_non_unique_public_key_hash: 0, + verify_identity_id_by_non_unique_public_key_hash: 0, }, group: DriveVerifyGroupMethodVersions { verify_group_info: 0, diff --git a/packages/rs-platform-version/src/version/mocks/v2_test.rs b/packages/rs-platform-version/src/version/mocks/v2_test.rs index 9a11e69178a..b9d2e964a33 100644 --- a/packages/rs-platform-version/src/version/mocks/v2_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v2_test.rs @@ -200,7 +200,7 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { max_version: 0, default_current_version: 0, }, - identity_by_public_key_hash: FeatureVersionBounds { + identity_by_unique_public_key_hash: FeatureVersionBounds { min_version: 0, max_version: 0, default_current_version: 0, From 8d997084709fd5bb39f415ea26bd65adf1ffe71d Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 6 Mar 2025 21:04:45 +0700 Subject: [PATCH 2/2] more work --- .../protos/platform/v0/platform.proto | 7 +- .../mod.rs | 5 +- .../v0/mod.rs | 108 ++++++++----- .../src/query/identity_based_queries/mod.rs | 2 +- packages/rs-drive-abci/src/query/service.rs | 43 +++++- .../mod.rs | 2 +- .../v0/mod.rs | 4 +- .../mod.rs | 12 +- .../v0/mod.rs | 11 +- .../fetch/fetch_by_public_key_hashes/mod.rs | 2 +- .../src/drive/identity/fetch/prove/mod.rs | 2 +- .../mod.rs | 41 +++-- .../v0/mod.rs | 145 ++++++++---------- .../src/drive/identity/fetch/queries/mod.rs | 18 ++- ...non_unique_public_key_hash_double_proof.rs | 21 +++ packages/rs-drive/src/drive/identity/mod.rs | 4 + packages/rs-drive/src/verify/identity/mod.rs | 4 +- .../mod.rs | 43 ++++-- .../v0/mod.rs | 56 ++++--- .../mod.rs | 2 +- .../v0/mod.rs | 25 +-- 21 files changed, 340 insertions(+), 217 deletions(-) create mode 100644 packages/rs-drive/src/drive/identity/identity_and_non_unique_public_key_hash_double_proof.rs diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index 5cf0a4c7fdd..b2d0c3defef 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -636,9 +636,14 @@ message GetIdentityByNonUniquePublicKeyHashResponse { message IdentityResponse { optional bytes identity = 1; } + + message IdentityProvedResponse { + Proof grovedb_identity_public_key_hash_proof = 1; + optional bytes identity_proof_bytes = 2; // A hack, we return 2 proofs + } oneof result { IdentityResponse identity = 1; - Proof proof = 2; + IdentityProvedResponse proof = 2; } ResponseMetadata metadata = 3; // Metadata about the blockchain state diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs index 8bfd4ed12e3..33403fad6a5 100644 --- a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/mod.rs @@ -5,7 +5,10 @@ use crate::platform_types::platform_state::PlatformState; use crate::query::QueryValidationResult; use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_request::Version as RequestVersion; use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::Version as ResponseVersion; -use dapi_grpc::platform::v0::{GetIdentityByNonUniquePublicKeyHashRequest, GetIdentityByNonUniquePublicKeyHashResponse, GetIdentityByPublicKeyHashResponse}; +use dapi_grpc::platform::v0::{ + GetIdentityByNonUniquePublicKeyHashRequest, GetIdentityByNonUniquePublicKeyHashResponse, + GetIdentityByPublicKeyHashResponse, +}; use dpp::version::PlatformVersion; mod v0; diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs index 07f23174845..a9a3ac7dd42 100644 --- a/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/identity_based_queries/identity_by_non_unique_public_key_hash/v0/mod.rs @@ -7,7 +7,7 @@ use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_request: use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::{ get_identity_by_non_unique_public_key_hash_response_v0, GetIdentityByNonUniquePublicKeyHashResponseV0, }; -use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::get_identity_by_non_unique_public_key_hash_response_v0::IdentityResponse; +use dapi_grpc::platform::v0::get_identity_by_non_unique_public_key_hash_response::get_identity_by_non_unique_public_key_hash_response_v0::{IdentityProvedResponse, IdentityResponse}; use dpp::check_validation_result_with_data; use dpp::platform_value::{Bytes20, Bytes32}; use dpp::serialization::PlatformSerializable; @@ -19,7 +19,7 @@ impl Platform { &self, GetIdentityByNonUniquePublicKeyHashRequestV0 { public_key_hash, - start_after, + start_after, prove, }: GetIdentityByNonUniquePublicKeyHashRequestV0, platform_state: &PlatformState, @@ -33,46 +33,58 @@ impl Platform { ))); let start_after = if let Some(start_after) = start_after { - Some(check_validation_result_with_data!(Bytes32::from_vec(start_after) - .map(|bytes| bytes.0) - .map_err(|_| QueryError::InvalidArgument( - "public key hash must be 20 bytes long".to_string() - )))) + Some(check_validation_result_with_data!(Bytes32::from_vec( + start_after + ) + .map(|bytes| bytes.0) + .map_err(|_| QueryError::InvalidArgument( + "public key hash must be 20 bytes long".to_string() + )))) } else { None }; - let response = if prove { - let proof = self.drive.prove_full_identity_by_non_unique_public_key_hash( - public_key_hash, - start_after, - None, - platform_version, - )?; + let proof = self + .drive + .prove_full_identity_by_non_unique_public_key_hash( + public_key_hash, + start_after, + None, + platform_version, + )?; GetIdentityByNonUniquePublicKeyHashResponseV0 { - result: Some(get_identity_by_non_unique_public_key_hash_response_v0::Result::Proof( - self.response_proof_v0(platform_state, proof), - )), + result: Some( + get_identity_by_non_unique_public_key_hash_response_v0::Result::Proof( + IdentityProvedResponse { + grovedb_identity_public_key_hash_proof: Some(self.response_proof_v0( + platform_state, + proof.identity_id_public_key_hash_proof, + )), + identity_proof_bytes: proof.identity_proof, + }, + ), + ), metadata: Some(self.response_metadata_v0(platform_state)), } } else { - let maybe_identity = self.drive.fetch_full_identity_by_non_unique_public_key_hash( - public_key_hash, - start_after, - None, - platform_version, - )?; - - let serialized_identity = maybe_identity.map(|identity| - - identity - .serialize_consume_to_bytes() - .map_err(Error::Protocol) - - ).transpose()?; - + let maybe_identity = self + .drive + .fetch_full_identity_by_non_unique_public_key_hash( + public_key_hash, + start_after, + None, + platform_version, + )?; + + let serialized_identity = maybe_identity + .map(|identity| { + identity + .serialize_consume_to_bytes() + .map_err(Error::Protocol) + }) + .transpose()?; GetIdentityByNonUniquePublicKeyHashResponseV0 { metadata: Some(self.response_metadata_v0(platform_state)), @@ -94,8 +106,8 @@ impl Platform { mod tests { use super::*; use crate::query::tests::setup_platform; - use dpp::dashcore::Network; use dapi_grpc::platform::v0::ResponseMetadata; + use dpp::dashcore::Network; #[test] fn test_invalid_public_key_hash() { @@ -132,12 +144,24 @@ mod tests { .query_identity_by_non_unique_public_key_hash_v0(request, &state, version) .expect("expected query to succeed"); - assert_eq!(result.data, Some(GetIdentityByNonUniquePublicKeyHashResponseV0 { - metadata: Some(ResponseMetadata { height: 0, core_chain_locked_height: 0, epoch: 0, time_ms: 0, protocol_version: 9, chain_id: "chain_id".to_string() }), - result: Some(get_identity_by_non_unique_public_key_hash_response_v0::Result::Identity(IdentityResponse { - identity: None, - })), - })); + assert_eq!( + result.data, + Some(GetIdentityByNonUniquePublicKeyHashResponseV0 { + metadata: Some(ResponseMetadata { + height: 0, + core_chain_locked_height: 0, + epoch: 0, + time_ms: 0, + protocol_version: 9, + chain_id: "chain_id".to_string() + }), + result: Some( + get_identity_by_non_unique_public_key_hash_response_v0::Result::Identity( + IdentityResponse { identity: None } + ) + ), + }) + ); } #[test] @@ -158,9 +182,9 @@ mod tests { assert!(matches!( result.data, Some(GetIdentityByNonUniquePublicKeyHashResponseV0 { - result: Some(get_identity_by_non_unique_public_key_hash_response_v0::Result::Proof( - _ - )), + result: Some( + get_identity_by_non_unique_public_key_hash_response_v0::Result::Proof(_) + ), metadata: Some(_), }) )); diff --git a/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs b/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs index f42ff1c4412..98b92b25128 100644 --- a/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs +++ b/packages/rs-drive-abci/src/query/identity_based_queries/mod.rs @@ -3,8 +3,8 @@ mod balance_and_revision; mod balances; mod identities_contract_keys; mod identity; -mod identity_by_unique_public_key_hash; mod identity_by_non_unique_public_key_hash; +mod identity_by_unique_public_key_hash; mod identity_contract_nonce; mod identity_nonce; mod keys; diff --git a/packages/rs-drive-abci/src/query/service.rs b/packages/rs-drive-abci/src/query/service.rs index 09a0dc9853e..9d77f180745 100644 --- a/packages/rs-drive-abci/src/query/service.rs +++ b/packages/rs-drive-abci/src/query/service.rs @@ -9,7 +9,41 @@ use crate::rpc::core::DefaultCoreRPC; use crate::utils::spawn_blocking_task_with_name_if_supported; use async_trait::async_trait; use dapi_grpc::platform::v0::platform_server::Platform as PlatformService; -use dapi_grpc::platform::v0::{BroadcastStateTransitionRequest, BroadcastStateTransitionResponse, GetConsensusParamsRequest, GetConsensusParamsResponse, GetContestedResourceIdentityVotesRequest, GetContestedResourceIdentityVotesResponse, GetContestedResourceVoteStateRequest, GetContestedResourceVoteStateResponse, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetContestedResourcesRequest, GetContestedResourcesResponse, GetCurrentQuorumsInfoRequest, GetCurrentQuorumsInfoResponse, GetDataContractHistoryRequest, GetDataContractHistoryResponse, GetDataContractRequest, GetDataContractResponse, GetDataContractsRequest, GetDataContractsResponse, GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, GetEvonodesProposedEpochBlocksResponse, GetGroupActionSignersRequest, GetGroupActionSignersResponse, GetGroupActionsRequest, GetGroupActionsResponse, GetGroupInfoRequest, GetGroupInfoResponse, GetGroupInfosRequest, GetGroupInfosResponse, GetIdentitiesBalancesRequest, GetIdentitiesBalancesResponse, GetIdentitiesContractKeysRequest, GetIdentitiesContractKeysResponse, GetIdentitiesTokenBalancesRequest, GetIdentitiesTokenBalancesResponse, GetIdentitiesTokenInfosRequest, GetIdentitiesTokenInfosResponse, GetIdentityBalanceAndRevisionRequest, GetIdentityBalanceAndRevisionResponse, GetIdentityBalanceRequest, GetIdentityBalanceResponse, GetIdentityByNonUniquePublicKeyHashRequest, GetIdentityByNonUniquePublicKeyHashResponse, GetIdentityByPublicKeyHashRequest, GetIdentityByPublicKeyHashResponse, GetIdentityContractNonceRequest, GetIdentityContractNonceResponse, GetIdentityKeysRequest, GetIdentityKeysResponse, GetIdentityNonceRequest, GetIdentityNonceResponse, GetIdentityRequest, GetIdentityResponse, GetIdentityTokenBalancesRequest, GetIdentityTokenBalancesResponse, GetIdentityTokenInfosRequest, GetIdentityTokenInfosResponse, GetPathElementsRequest, GetPathElementsResponse, GetPrefundedSpecializedBalanceRequest, GetPrefundedSpecializedBalanceResponse, GetProofsRequest, GetProofsResponse, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, GetStatusRequest, GetStatusResponse, GetTokenPreProgrammedDistributionsRequest, GetTokenPreProgrammedDistributionsResponse, GetTokenStatusesRequest, GetTokenStatusesResponse, GetTokenTotalSupplyRequest, GetTokenTotalSupplyResponse, GetTotalCreditsInPlatformRequest, GetTotalCreditsInPlatformResponse, GetVotePollsByEndDateRequest, GetVotePollsByEndDateResponse, WaitForStateTransitionResultRequest, WaitForStateTransitionResultResponse}; +use dapi_grpc::platform::v0::{ + BroadcastStateTransitionRequest, BroadcastStateTransitionResponse, GetConsensusParamsRequest, + GetConsensusParamsResponse, GetContestedResourceIdentityVotesRequest, + GetContestedResourceIdentityVotesResponse, GetContestedResourceVoteStateRequest, + GetContestedResourceVoteStateResponse, GetContestedResourceVotersForIdentityRequest, + GetContestedResourceVotersForIdentityResponse, GetContestedResourcesRequest, + GetContestedResourcesResponse, GetCurrentQuorumsInfoRequest, GetCurrentQuorumsInfoResponse, + GetDataContractHistoryRequest, GetDataContractHistoryResponse, GetDataContractRequest, + GetDataContractResponse, GetDataContractsRequest, GetDataContractsResponse, + GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, + GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, + GetEvonodesProposedEpochBlocksResponse, GetGroupActionSignersRequest, + GetGroupActionSignersResponse, GetGroupActionsRequest, GetGroupActionsResponse, + GetGroupInfoRequest, GetGroupInfoResponse, GetGroupInfosRequest, GetGroupInfosResponse, + GetIdentitiesBalancesRequest, GetIdentitiesBalancesResponse, GetIdentitiesContractKeysRequest, + GetIdentitiesContractKeysResponse, GetIdentitiesTokenBalancesRequest, + GetIdentitiesTokenBalancesResponse, GetIdentitiesTokenInfosRequest, + GetIdentitiesTokenInfosResponse, GetIdentityBalanceAndRevisionRequest, + GetIdentityBalanceAndRevisionResponse, GetIdentityBalanceRequest, GetIdentityBalanceResponse, + GetIdentityByNonUniquePublicKeyHashRequest, GetIdentityByNonUniquePublicKeyHashResponse, + GetIdentityByPublicKeyHashRequest, GetIdentityByPublicKeyHashResponse, + GetIdentityContractNonceRequest, GetIdentityContractNonceResponse, GetIdentityKeysRequest, + GetIdentityKeysResponse, GetIdentityNonceRequest, GetIdentityNonceResponse, GetIdentityRequest, + GetIdentityResponse, GetIdentityTokenBalancesRequest, GetIdentityTokenBalancesResponse, + GetIdentityTokenInfosRequest, GetIdentityTokenInfosResponse, GetPathElementsRequest, + GetPathElementsResponse, GetPrefundedSpecializedBalanceRequest, + GetPrefundedSpecializedBalanceResponse, GetProofsRequest, GetProofsResponse, + GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, + GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, + GetStatusRequest, GetStatusResponse, GetTokenPreProgrammedDistributionsRequest, + GetTokenPreProgrammedDistributionsResponse, GetTokenStatusesRequest, GetTokenStatusesResponse, + GetTokenTotalSupplyRequest, GetTokenTotalSupplyResponse, GetTotalCreditsInPlatformRequest, + GetTotalCreditsInPlatformResponse, GetVotePollsByEndDateRequest, GetVotePollsByEndDateResponse, + WaitForStateTransitionResultRequest, WaitForStateTransitionResultResponse, +}; use dapi_grpc::tonic::{Code, Request, Response, Status}; use dpp::version::PlatformVersion; use std::fmt::Debug; @@ -378,13 +412,16 @@ impl PlatformService for QueryService { .await } - async fn get_identity_by_non_unique_public_key_hash(&self, request: Request) -> Result, Status> { + async fn get_identity_by_non_unique_public_key_hash( + &self, + request: Request, + ) -> Result, Status> { self.handle_blocking_query( request, Platform::::query_identity_by_non_unique_public_key_hash, "get_identity_by_non_unique_public_key_hash", ) - .await + .await } async fn wait_for_state_transition_result( diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs index 58438b01e71..7945cb0799c 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/mod.rs @@ -25,7 +25,7 @@ impl Drive { pub fn fetch_full_identity_by_non_unique_public_key_hash( &self, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs index 44fb166d486..fa6dd8b1618 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_full_identity_by_non_unique_public_key_hash/v0/mod.rs @@ -13,7 +13,7 @@ impl Drive { pub(super) fn fetch_full_identity_by_non_unique_public_key_hash_v0( &self, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { @@ -31,7 +31,7 @@ impl Drive { pub(super) fn fetch_full_identity_by_non_unique_public_key_hash_operations_v0( &self, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, drive_operations: &mut Vec, platform_version: &PlatformVersion, diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs index 892d91c7bf5..13c3e8111f8 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/mod.rs @@ -2,9 +2,9 @@ mod v0; use crate::drive::Drive; use crate::error::{drive::DriveError, Error}; +use crate::fees::op::LowLevelDriveOperation; use grovedb::TransactionArg; use platform_version::version::PlatformVersion; -use crate::fees::op::LowLevelDriveOperation; impl Drive { /// Fetches identity ids from storage based on a non-unique public key hash. @@ -25,11 +25,12 @@ impl Drive { &self, public_key_hash: [u8; 20], limit: Option, - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { - match platform_version.drive + match platform_version + .drive .methods .identity .fetch @@ -55,12 +56,13 @@ impl Drive { &self, public_key_hash: [u8; 20], limit: Option, - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, drive_operations: &mut Vec, platform_version: &PlatformVersion, ) -> Result, Error> { - match platform_version.drive + match platform_version + .drive .methods .identity .fetch diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs index 1eb970654f7..0eeacb54b23 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_non_unique_public_key_hash/v0/mod.rs @@ -8,8 +8,8 @@ use grovedb::query_result_type::QueryResultType; use grovedb::{PathQuery, TransactionArg}; -use std::ops::RangeFull; use platform_version::version::PlatformVersion; +use std::ops::RangeFull; impl Drive { /// Fetches identity ids from storage. @@ -17,7 +17,7 @@ impl Drive { &self, public_key_hash: [u8; 20], limit: Option, - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { @@ -37,7 +37,7 @@ impl Drive { &self, public_key_hash: [u8; 20], limit: Option, - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, drive_operations: &mut Vec, platform_version: &PlatformVersion, @@ -49,10 +49,7 @@ impl Drive { QueryItem::RangeAfter(after.to_vec()..), ) } else { - PathQuery::new_single_query_item( - non_unique_key_hashes, - QueryItem::RangeFull(RangeFull), - ) + PathQuery::new_single_query_item(non_unique_key_hashes, QueryItem::RangeFull(RangeFull)) }; path_query.query.limit = limit; diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs index 849fdbe8626..cbd75b76d42 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs @@ -1,4 +1,5 @@ mod fetch_full_identities_by_unique_public_key_hashes; +mod fetch_full_identity_by_non_unique_public_key_hash; mod fetch_full_identity_by_unique_public_key_hash; mod fetch_identity_id_by_unique_public_key_hash; mod fetch_identity_ids_by_non_unique_public_key_hash; @@ -7,7 +8,6 @@ mod has_any_of_unique_public_key_hashes; mod has_non_unique_public_key_hash; mod has_non_unique_public_key_hash_already_for_identity; mod has_unique_public_key_hash; -mod fetch_full_identity_by_non_unique_public_key_hash; #[cfg(feature = "server")] #[cfg(test)] diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs index 01678cef1eb..7ca607c9f0a 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/mod.rs @@ -1,8 +1,8 @@ mod prove_full_identities; mod prove_full_identities_by_unique_public_key_hashes; mod prove_full_identity; +mod prove_full_identity_by_non_unique_public_key_hash; mod prove_full_identity_by_unique_public_key_hash; mod prove_identities_contract_keys; mod prove_identity_id_by_unique_public_key_hash; mod prove_identity_ids_by_unique_public_key_hashes; -mod prove_full_identity_by_non_unique_public_key_hash; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs index 5703fc6920b..5712e0df0d4 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/mod.rs @@ -4,31 +4,54 @@ use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; +use crate::drive::identity::identity_and_non_unique_public_key_hash_double_proof::IdentityAndNonUniquePublicKeyHashDoubleProof; use dpp::version::PlatformVersion; use grovedb::TransactionArg; impl Drive { - /// Fetches an identity with all its information from storage. + /// Generates a proof for an identity associated with a given non-unique public key hash. /// - /// This function uses the versioning system to call the appropriate handler based on the provided `DriveVersion`. + /// This function retrieves an identity along with its associated proofs from storage. + /// It utilizes versioning to call the appropriate handler based on the provided + /// `PlatformVersion`. /// /// # Arguments /// - /// * `public_key_hash` - The public key hash for which to fetch the identity. - /// * `after` - An identity ID after which we want to get back our identity. Basically "don't get back this identity, get the next one" - /// * `transaction` - Transaction arguments. - /// * `drive_version` - A reference to the drive version. + /// - `public_key_hash` - A 20-byte array representing the hash of the public key + /// for which the identity should be fetched. + /// - `after` - An optional identity ID specifying the starting point for retrieval. + /// If provided, the function will return the identity that appears after the given ID, + /// ensuring that the specified identity itself is not included. + /// - `transaction` - A transaction argument used for database operations. + /// - `platform_version` - A reference to the platform version, ensuring that the + /// correct version-specific function is used. /// /// # Returns /// - /// Returns a `Result` containing a vector of bytes representing the proved identity, otherwise an `Error` if the operation fails or the version is not supported. + /// Returns a `Result` containing an [`IdentityAndNonUniquePublicKeyHashDoubleProof`], which + /// includes both the proof of the identity and the proof linking the public key hash to + /// an identity ID. If the operation fails or the platform version is unsupported, an `Error` + /// is returned. + /// + /// # Errors + /// + /// This function will return an `Error` if: + /// - The identity retrieval operation fails. + /// - The provided public key hash does not correspond to a known identity. + /// - The requested platform version is unknown or not supported. + /// + /// # Versioning + /// + /// - Currently, only version `0` of `prove_full_identity_by_non_unique_public_key_hash` + /// is implemented. If an unsupported version is provided, an `UnknownVersionMismatch` + /// error is returned. pub fn prove_full_identity_by_non_unique_public_key_hash( &self, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, platform_version: &PlatformVersion, - ) -> Result, Error> { + ) -> Result { match platform_version .drive .methods diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs index 7231d8bee9b..93c8d26c519 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_non_unique_public_key_hash/v0/mod.rs @@ -2,6 +2,7 @@ use crate::drive::Drive; use crate::error::Error; +use crate::drive::identity::identity_and_non_unique_public_key_hash_double_proof::IdentityAndNonUniquePublicKeyHashDoubleProof; use dpp::version::PlatformVersion; use grovedb::TransactionArg; @@ -10,10 +11,10 @@ impl Drive { pub(super) fn prove_full_identity_by_non_unique_public_key_hash_v0( &self, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, transaction: TransactionArg, platform_version: &PlatformVersion, - ) -> Result, Error> { + ) -> Result { let identity_ids = self.fetch_identity_ids_by_non_unique_public_key_hash_operations( public_key_hash, Some(1), @@ -22,36 +23,38 @@ impl Drive { &mut vec![], platform_version, )?; - if let Some(identity_id) = identity_ids.first() { - let query = Self::full_identity_with_non_unique_public_key_hash_query( - public_key_hash, - *identity_id, - after, - &platform_version.drive.grove_version, - )?; - self.grove_get_proved_path_query( - &query, + // We only prove the absence of the public key hash + let mut path_query = + Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); + path_query.query.limit = Some(1); + let identity_id_public_key_hash_proof = self.grove_get_proved_path_query( + &path_query, + transaction, + &mut vec![], + &platform_version.drive, + )?; + let identity_proof = if let Some(identity_id) = identity_ids.first() { + let full_identity_query = + Self::full_identity_query(&identity_id, &platform_version.drive.grove_version)?; + Some(self.grove_get_proved_path_query( + &full_identity_query, transaction, &mut vec![], &platform_version.drive, - ) + )?) } else { - // We only prove the absence of the public key hash - let query = Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); - self.grove_get_proved_path_query( - &query, - transaction, - &mut vec![], - &platform_version.drive, - ) - } + None + }; + + Ok(IdentityAndNonUniquePublicKeyHashDoubleProof { + identity_proof, + identity_id_public_key_hash_proof, + }) } } #[cfg(test)] mod tests { - use rand::prelude::StdRng; - use rand::SeedableRng; use super::*; use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; use dpp::block::block_info::BlockInfo; @@ -60,9 +63,11 @@ mod tests { use dpp::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMethodsV0; use dpp::identity::{Identity, IdentityPublicKey, KeyType}; use dpp::version::PlatformVersion; + use rand::prelude::StdRng; + use rand::SeedableRng; #[test] - fn should_prove_a_single_identity() { + fn should_prove_a_single_identity_with_non_unique_key() { let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -84,64 +89,27 @@ mod tests { let first_key_hash = identity .public_keys() .values() - .find(|public_key| public_key.key_type().is_unique_key_type()) + .find(|public_key| !public_key.key_type().is_unique_key_type()) .expect("expected a unique key") .public_key_hash() .expect("expected to hash data"); let proof = drive - .prove_full_identity_by_unique_public_key_hash(first_key_hash, None, platform_version) - .expect("should not error when proving an identity"); - - let (_, proved_identity) = Drive::verify_full_identity_by_unique_public_key_hash( - proof.as_slice(), - first_key_hash, - platform_version, - ) - .expect("expect that this be verified"); - - assert_eq!(proved_identity, Some(identity)); - } - - #[test] - fn should_prove_a_single_identity_with_non_unique_key() { - let drive = setup_drive_with_initial_state_structure(None); - - let platform_version = PlatformVersion::latest(); - - let identity = Identity::random_identity(3, Some(14), platform_version) - .expect("expected a random identity"); - - drive - .add_new_identity( - identity.clone(), - false, - &BlockInfo::default(), - true, + .prove_full_identity_by_non_unique_public_key_hash( + first_key_hash, + None, None, platform_version, ) - .expect("expected to add an identity"); - - let first_key_hash = identity - .public_keys() - .values() - .find(|public_key| !public_key.key_type().is_unique_key_type()) - .expect("expected a unique key") - .public_key_hash() - .expect("expected to hash data"); - - let proof = drive - .prove_full_identity_by_non_unique_public_key_hash(first_key_hash, None, None, platform_version) .expect("should not error when proving an identity"); let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( - proof.as_slice(), + &proof, first_key_hash, None, platform_version, ) - .expect("expect that this be verified"); + .expect("expect that this be verified"); assert_eq!(proved_identity, Some(identity)); } @@ -159,12 +127,14 @@ mod tests { .expect("expected a random identity"); let mut rng = StdRng::seed_from_u64(506); - - let key = IdentityPublicKey::random_voting_key_with_rng(3, &mut rng, platform_version).expect("expected key").0; + + let key = IdentityPublicKey::random_voting_key_with_rng(3, &mut rng, platform_version) + .expect("expected key") + .0; identity_1.add_public_key(key.clone()); identity_2.add_public_key(key.clone()); - + drive .add_new_identity( identity_1.clone(), @@ -186,48 +156,63 @@ mod tests { platform_version, ) .expect("expected to add an identity"); - + let key_hash = key.public_key_hash().expect("expected key hash"); let proof = drive - .prove_full_identity_by_non_unique_public_key_hash(key_hash, None, None, platform_version) + .prove_full_identity_by_non_unique_public_key_hash( + key_hash, + None, + None, + platform_version, + ) .expect("should not error when proving an identity"); let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( - proof.as_slice(), + &proof, key_hash, None, platform_version, ) - .expect("expect that this be verified"); + .expect("expect that this be verified"); assert_eq!(proved_identity, Some(identity_1.clone())); let proof = drive - .prove_full_identity_by_non_unique_public_key_hash(key_hash, Some(identity_1.id().to_buffer()), None, platform_version) + .prove_full_identity_by_non_unique_public_key_hash( + key_hash, + Some(identity_1.id().to_buffer()), + None, + platform_version, + ) .expect("should not error when proving an identity"); let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( - proof.as_slice(), + &proof, key_hash, Some(identity_1.id().to_buffer()), platform_version, ) - .expect("expect that this be verified"); + .expect("expect that this be verified"); assert_eq!(proved_identity, Some(identity_2.clone())); let proof = drive - .prove_full_identity_by_non_unique_public_key_hash(key_hash, Some(identity_2.id().to_buffer()), None, platform_version) + .prove_full_identity_by_non_unique_public_key_hash( + key_hash, + Some(identity_2.id().to_buffer()), + None, + platform_version, + ) .expect("should not error when proving an identity"); let (_, proved_identity) = Drive::verify_full_identity_by_non_unique_public_key_hash( - proof.as_slice(), + &proof, key_hash, Some(identity_2.id().to_buffer()), platform_version, ) - .expect("expect that this be verified"); + .expect("expect that this be verified"); assert_eq!(proved_identity, None); } diff --git a/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs b/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs index 685b7353c46..6e1b1e4b65d 100644 --- a/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/queries/mod.rs @@ -1,6 +1,9 @@ use crate::drive::balances::balance_path_vec; use crate::drive::identity::key::fetch::IdentityKeysRequest; -use crate::drive::{identity_tree_path_vec, non_unique_key_hashes_tree_path, non_unique_key_hashes_tree_path_vec, unique_key_hashes_tree_path_vec, Drive}; +use crate::drive::{ + identity_tree_path_vec, non_unique_key_hashes_tree_path, non_unique_key_hashes_tree_path_vec, + unique_key_hashes_tree_path_vec, Drive, +}; use std::ops::RangeFull; use crate::error::Error; @@ -92,13 +95,14 @@ impl Drive { /// The query for proving an identity id from a non-unique public key hash. /// This should be used for absence proofs - pub fn identity_id_by_non_unique_public_key_hash_query(public_key_hash: [u8; 20], after: Option<[u8;32]>) -> PathQuery { + pub fn identity_id_by_non_unique_public_key_hash_query( + public_key_hash: [u8; 20], + after: Option<[u8; 32]>, + ) -> PathQuery { let non_unique_key_hashes = non_unique_key_hashes_tree_path_vec(); let mut query = Query::new_single_key(public_key_hash.to_vec()); let sub_query = if let Some(after) = after { - Query::new_single_query_item(QueryItem::RangeFrom( - after.to_vec().., - )) + Query::new_single_query_item(QueryItem::RangeFrom(after.to_vec()..)) } else { Query::new_range_full() }; @@ -233,7 +237,7 @@ impl Drive { pub fn full_identity_with_non_unique_public_key_hash_query( public_key_hash: [u8; 20], identity_id: [u8; 32], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, grove_version: &GroveVersion, ) -> Result { let full_identity_query = Self::full_identity_query(&identity_id, grove_version)?; @@ -243,7 +247,7 @@ impl Drive { vec![&full_identity_query, &identity_id_by_public_key_hash_query], grove_version, ) - .map_err(Error::GroveDB) + .map_err(Error::GroveDB) } /// The query full identities with key hashes too diff --git a/packages/rs-drive/src/drive/identity/identity_and_non_unique_public_key_hash_double_proof.rs b/packages/rs-drive/src/drive/identity/identity_and_non_unique_public_key_hash_double_proof.rs new file mode 100644 index 00000000000..ccd439ca080 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/identity_and_non_unique_public_key_hash_double_proof.rs @@ -0,0 +1,21 @@ +/// Represents a proof containing an optional identity proof and a required +/// proof for the identity ID and non-unique public key hash. +/// +/// This struct is used to verify the authenticity and validity of an identity +/// and its associated non-unique public key hash. +/// +/// # Fields +/// +/// * `identity_proof` - An optional proof for the identity, represented as a +/// serialized byte vector. This may be `None` if no additional proof is required. +/// * `identity_id_public_key_hash_proof` - A required proof verifying the +/// association between an identity ID and its non-unique public key hash, +/// stored as a serialized byte vector. +pub struct IdentityAndNonUniquePublicKeyHashDoubleProof { + /// Optional proof of identity, stored as a serialized byte vector. + pub identity_proof: Option>, + + /// Proof linking an identity ID to a non-unique public key hash, + /// stored as a serialized byte vector. + pub identity_id_public_key_hash_proof: Vec, +} diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index 1922e74b884..a75be0ea563 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -40,6 +40,10 @@ pub mod key; #[cfg(feature = "server")] pub mod update; +/// A module for a struct encapsulating an identity and a non-unique public key hash to identity id proof +#[cfg(any(feature = "server", feature = "verify"))] +pub mod identity_and_non_unique_public_key_hash_double_proof; + use crate::drive::identity::contract_info::ContractInfoStructure; use crate::error::drive::DriveError; use crate::error::Error; diff --git a/packages/rs-drive/src/verify/identity/mod.rs b/packages/rs-drive/src/verify/identity/mod.rs index 9e0482bc79e..a9308182abb 100644 --- a/packages/rs-drive/src/verify/identity/mod.rs +++ b/packages/rs-drive/src/verify/identity/mod.rs @@ -1,15 +1,15 @@ mod verify_full_identities_by_public_key_hashes; mod verify_full_identity_by_identity_id; -mod verify_full_identity_by_unique_public_key_hash; mod verify_full_identity_by_non_unique_public_key_hash; +mod verify_full_identity_by_unique_public_key_hash; mod verify_identities_contract_keys; mod verify_identity_balance_and_revision_for_identity_id; mod verify_identity_balance_for_identity_id; mod verify_identity_balances_for_identity_ids; mod verify_identity_contract_nonce; +mod verify_identity_id_by_non_unique_public_key_hash; mod verify_identity_id_by_unique_public_key_hash; mod verify_identity_ids_by_unique_public_key_hashes; mod verify_identity_keys_by_identity_id; mod verify_identity_nonce; mod verify_identity_revision_for_identity_id; -mod verify_identity_id_by_non_unique_public_key_hash; diff --git a/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs index b290bec46fe..4e593caeb67 100644 --- a/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/mod.rs @@ -10,37 +10,50 @@ use crate::verify::RootHash; pub use dpp::prelude::Identity; +use crate::drive::identity::identity_and_non_unique_public_key_hash_double_proof::IdentityAndNonUniquePublicKeyHashDoubleProof; use dpp::version::PlatformVersion; impl Drive { - /// Verifies the full identity of a user by their public key hash. + /// Verifies the full identity of a user using their non-unique public key hash. + /// + /// This function acts as a dispatcher that selects the appropriate version-specific + /// verification method based on the provided platform version. /// /// # Parameters /// - /// - `proof`: A byte slice representing the proof of authentication from the user. - /// - `public_key_hash`: A 20-byte array representing the hash of the public key of the user. - /// - `after`: A 32 byte array representing an identity after which we want to get the identity. - /// - `platform_version`: The platform version against which to verify the identity. + /// - `proof`: A proof containing both the identity proof (if applicable) and the + /// proof linking the public key hash to an identity ID. + /// - `public_key_hash`: A 20-byte array representing the hash of the user's public key. + /// - `after`: An optional 32-byte array specifying an identity after which + /// the search should begin when retrieving the identity. + /// - `platform_version`: A reference to the platform version, ensuring that + /// the correct verification method is used. /// /// # Returns /// - /// If the verification is successful, it returns a `Result` with a tuple of `RootHash` and - /// an `Option` of `Identity`. The `RootHash` represents the root hash of GroveDB, and the - /// `Option` represents the full identity of the user if it exists. + /// Returns a `Result` containing: + /// - `RootHash`: The root hash of GroveDB after verification. + /// - `Option`: The full identity of the user, if it exists. /// - /// # Errors + /// If no identity is found, the returned `Option` will be `None`. /// - /// Returns an `Error` if: + /// # Errors /// - /// - The proof of authentication is not valid. + /// This function returns an `Error` if: + /// - The provided proof is invalid. /// - The public key hash does not correspond to a valid identity ID. - /// - The identity ID does not correspond to a valid full identity. - /// - An unknown or unsupported platform version is provided. + /// - The identity ID exists but does not correspond to a valid full identity. + /// - The provided platform version is unknown or unsupported. + /// + /// # Versioning /// + /// - Currently, only version `0` of `verify_full_identity_by_non_unique_public_key_hash` + /// is implemented. If an unsupported version is provided, an `UnknownVersionMismatch` + /// error is returned. pub fn verify_full_identity_by_non_unique_public_key_hash( - proof: &[u8], + proof: &IdentityAndNonUniquePublicKeyHashDoubleProof, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, platform_version: &PlatformVersion, ) -> Result<(RootHash, Option), Error> { match platform_version diff --git a/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs index ee3024d1a7a..ccb81c1d6fb 100644 --- a/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_full_identity_by_non_unique_public_key_hash/v0/mod.rs @@ -6,56 +6,70 @@ use crate::verify::RootHash; pub use dpp::prelude::Identity; +use crate::drive::identity::identity_and_non_unique_public_key_hash_double_proof::IdentityAndNonUniquePublicKeyHashDoubleProof; +use crate::error::proof::ProofError; use dpp::version::PlatformVersion; impl Drive { - /// Verifies the full identity of a user by their public key hash. + /// Verifies the full identity of a user using their non-unique public key hash. /// - /// This function takes a byte slice `proof` and a 20-byte array `public_key_hash` as arguments, - /// then it verifies the identity of the user with the given public key hash. + /// This function performs a two-step verification process: + /// 1. It verifies the identity ID associated with the given public key hash + /// by calling [`verify_identity_id_by_non_unique_public_key_hash()`]. + /// 2. If an identity ID is found, it then verifies the full identity by calling + /// [`verify_full_identity_by_identity_id()`]. /// - /// The `proof` should contain the proof of authentication from the user. - /// The `public_key_hash` should contain the hash of the public key of the user. + /// # Arguments /// - /// The function first verifies the identity ID associated with the given public key hash - /// by calling `verify_identity_id_by_non_unique_public_key_hash()`. It then uses this identity ID to verify - /// the full identity by calling `verify_full_identity_by_identity_id()`. + /// * `proof` - A proof containing both the identity proof (if applicable) and + /// the proof linking the public key hash to an identity ID. + /// * `public_key_hash` - A 20-byte array representing the hash of the user's public key. + /// * `after` - An optional 32-byte array used to specify a search point in the proof verification process. + /// * `platform_version` - A reference to the platform version, ensuring compatibility. /// /// # Returns /// - /// If the verification is successful, it returns a `Result` with a tuple of `RootHash` and - /// an `Option` of `Identity`. The `RootHash` represents the root hash of GroveDB, and the - /// `Option` represents the full identity of the user if it exists. + /// If verification is successful, returns a `Result` containing: + /// - `RootHash` - The root hash of GroveDB after verification. + /// - `Option` - The full identity of the user, if it exists. /// - /// If the verification fails at any point, it will return an `Error`. + /// If no identity is found, the returned `Option` will be `None`. /// /// # Errors /// /// This function will return an `Error` if: - /// - /// * The proof of authentication is not valid. + /// * The provided proof is invalid. /// * The public key hash does not correspond to a valid identity ID. - /// * The identity ID does not correspond to a valid full identity. + /// * The identity ID exists but the associated identity proof is missing. + /// * The identity verification process fails. + /// + /// # Inline Optimization /// + /// This function is marked with `#[inline(always)]` to hint the compiler to + /// aggressively inline it for performance optimization. #[inline(always)] pub(super) fn verify_full_identity_by_non_unique_public_key_hash_v0( - proof: &[u8], + proof: &IdentityAndNonUniquePublicKeyHashDoubleProof, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, platform_version: &PlatformVersion, ) -> Result<(RootHash, Option), Error> { let (root_hash, identity_id) = Self::verify_identity_id_by_non_unique_public_key_hash( - proof, - true, + &proof.identity_id_public_key_hash_proof, + false, public_key_hash, after, platform_version, )?; let maybe_identity = identity_id .map(|identity_id| { + let Some(identity_proof) = &proof.identity_proof else { + return Err(Error::Proof(ProofError::IncompleteProof("identity is not in proof even though identity id is set from non unique public key hash"))); + }; + println!("hex {}", hex::encode(&identity_proof)); Self::verify_full_identity_by_identity_id( - proof, - true, + identity_proof.as_slice(), + false, identity_id, platform_version, ) diff --git a/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs index 5cf78fb3964..0d1ccae9f99 100644 --- a/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/mod.rs @@ -38,7 +38,7 @@ impl Drive { proof: &[u8], is_proof_subset: bool, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, platform_version: &PlatformVersion, ) -> Result<(RootHash, Option<[u8; 32]>), Error> { match platform_version diff --git a/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs index 01429e1e628..1d3730b5562 100644 --- a/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/verify/identity/verify_identity_id_by_non_unique_public_key_hash/v0/mod.rs @@ -38,23 +38,16 @@ impl Drive { proof: &[u8], is_proof_subset: bool, public_key_hash: [u8; 20], - after: Option<[u8;32]>, + after: Option<[u8; 32]>, platform_version: &PlatformVersion, ) -> Result<(RootHash, Option<[u8; 32]>), Error> { - let mut path_query = Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); + let mut path_query = + Self::identity_id_by_non_unique_public_key_hash_query(public_key_hash, after); path_query.query.limit = Some(1); let (root_hash, mut proved_key_values) = if is_proof_subset { - GroveDb::verify_subset_query( - proof, - &path_query, - &platform_version.drive.grove_version, - )? + GroveDb::verify_subset_query(proof, &path_query, &platform_version.drive.grove_version)? } else { - GroveDb::verify_query( - proof, - &path_query, - &platform_version.drive.grove_version, - )? + GroveDb::verify_query(proof, &path_query, &platform_version.drive.grove_version)? }; if proved_key_values.len() == 1 { @@ -65,11 +58,9 @@ impl Drive { .to_string(), ))); } - let identity_id = key - .try_into() - .map_err(|_| { - Error::Proof(ProofError::IncorrectValueSize("value size is incorrect")) - })?; + let identity_id = key.try_into().map_err(|_| { + Error::Proof(ProofError::IncorrectValueSize("value size is incorrect")) + })?; Ok((root_hash, Some(identity_id))) } else { Ok((root_hash, None))