diff --git a/packages/rs-dpp/src/identity/identity.rs b/packages/rs-dpp/src/identity/identity.rs index f6644ee1ac6..478fbd7fd11 100644 --- a/packages/rs-dpp/src/identity/identity.rs +++ b/packages/rs-dpp/src/identity/identity.rs @@ -409,6 +409,23 @@ impl Identity { not_found_public_keys: Default::default(), } } + + /// Convenience method to get Partial Identity Info + pub fn into_partial_identity_info_no_balance(self) -> PartialIdentity { + let Identity { + id, + public_keys, + revision, + .. + } = self; + PartialIdentity { + id, + loaded_public_keys: public_keys, + balance: None, + revision: Some(revision), + not_found_public_keys: Default::default(), + } + } } impl TryFrom for Identity { diff --git a/packages/rs-dpp/src/identity/identity_public_key/key_type.rs b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs index 3896d8cec20..58c5af6c094 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/key_type.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs @@ -131,7 +131,7 @@ impl KeyType { let secret_key = dashcore::secp256k1::SecretKey::new(&mut rng); let private_key = dashcore::PrivateKey::new(secret_key, Network::Dash); ( - ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()), + ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()).to_vec(), private_key.to_bytes(), ) } @@ -149,7 +149,7 @@ impl KeyType { let secret_key = dashcore::secp256k1::SecretKey::new(&mut rng); let private_key = dashcore::PrivateKey::new(secret_key, Network::Dash); ( - ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()), + ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()).to_vec(), private_key.to_bytes(), ) } diff --git a/packages/rs-dpp/src/identity/identity_public_key/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/mod.rs index 5ff52cb708c..a91625fb5da 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/mod.rs @@ -12,7 +12,7 @@ use anyhow::anyhow; #[cfg(feature = "cbor")] use ciborium::value::Value as CborValue; use dashcore::PublicKey as ECDSAPublicKey; -use platform_value::{BinaryData, ReplacementType, Value, ValueMapHelper}; +use platform_value::{BinaryData, Bytes20, ReplacementType, Value, ValueMapHelper}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::Value as JsonValue; @@ -27,6 +27,7 @@ use crate::util::cbor_value::{CborCanonicalMap, CborMapExtension}; use crate::util::hash::ripemd160_sha256; use crate::Convertible; use bincode::{config, Decode, Encode}; +use dashcore::hashes::Hash; use crate::identity::state_transition::identity_public_key_transitions::IdentityPublicKeyInCreation; use crate::util::vec; @@ -142,7 +143,7 @@ impl IdentityPublicKey { } /// Get the original public key hash - pub fn hash(&self) -> Result, ProtocolError> { + pub fn hash(&self) -> Result<[u8; 20], ProtocolError> { if self.data.is_empty() { return Err(ProtocolError::EmptyPublicKeyDataError); } @@ -160,7 +161,7 @@ impl IdentityPublicKey { ))); } }; - Ok(key.pubkey_hash().to_vec()) + Ok(key.pubkey_hash().into_inner()) } KeyType::BLS12_381 => { if self.data.len() != 48 { @@ -173,7 +174,7 @@ impl IdentityPublicKey { } } KeyType::ECDSA_HASH160 | KeyType::BIP13_SCRIPT_HASH | KeyType::EDDSA_25519_HASH160 => { - Ok(self.data.to_vec()) + Ok(Bytes20::from_vec(self.data.to_vec())?.into_buffer()) } } } diff --git a/packages/rs-dpp/src/identity/state_transition/identity_public_key_transitions/mod.rs b/packages/rs-dpp/src/identity/state_transition/identity_public_key_transitions/mod.rs index c694765f40b..40ff0b4e7c2 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_public_key_transitions/mod.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_public_key_transitions/mod.rs @@ -226,7 +226,9 @@ impl IdentityPublicKeyInCreation { /// Get the original public key hash pub fn hash_as_vec(&self) -> Result, ProtocolError> { - Into::::into(self).hash() + Into::::into(self) + .hash() + .map(|hash| hash.to_vec()) } /// Get the original public key hash diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs index 64f24984bf3..696190141f3 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition_identity_signed.rs @@ -68,7 +68,7 @@ where let public_key_compressed = get_compressed_public_ec_key(private_key)?; let pub_key_hash = ripemd160_sha256(&public_key_compressed); - if pub_key_hash != identity_public_key.data { + if identity_public_key.data != pub_key_hash { return Err(ProtocolError::InvalidSignaturePublicKeyError( InvalidSignaturePublicKeyError::new(identity_public_key.data.to_vec()), )); @@ -473,7 +473,7 @@ mod test { let mut keys = get_test_keys(); keys.identity_public_key.key_type = KeyType::ECDSA_HASH160; keys.identity_public_key.data = - BinaryData::new(ripemd160_sha256(keys.identity_public_key.data.as_slice())); + BinaryData::new(ripemd160_sha256(keys.identity_public_key.data.as_slice()).to_vec()); st.sign(&keys.identity_public_key, &keys.ec_private, &bls) .unwrap(); diff --git a/packages/rs-dpp/src/tests/identity/identity_public_key_spec.rs b/packages/rs-dpp/src/tests/identity/identity_public_key_spec.rs index 7ca44fa322f..b956e90fb5c 100644 --- a/packages/rs-dpp/src/tests/identity/identity_public_key_spec.rs +++ b/packages/rs-dpp/src/tests/identity/identity_public_key_spec.rs @@ -62,7 +62,7 @@ mod from_raw_object { "type": KeyType::BIP13_SCRIPT_HASH, "purpose": Purpose::AUTHENTICATION, "securityLevel": SecurityLevel::MASTER, - "data": "AuryIuMtRrl/VviQuyLD1l4nmxi9ogPzC9LT7tdpo0di", + "data": "n6I3y1cTf2efmnf3/oFvAmjpGQ8=", "readOnly": false }); @@ -72,8 +72,8 @@ mod from_raw_object { assert_eq!( public_key.hash().unwrap(), [ - 2, 234, 242, 34, 227, 45, 70, 185, 127, 86, 248, 144, 187, 34, 195, 214, 94, 39, - 155, 24, 189, 162, 3, 243, 11, 210, 211, 238, 215, 105, 163, 71, 98 + 159, 162, 55, 203, 87, 19, 127, 103, 159, 154, 119, 247, 254, 129, 111, 2, 104, + 233, 25, 15, ] ); } diff --git a/packages/rs-dpp/src/util/hash.rs b/packages/rs-dpp/src/util/hash.rs index 1d2c9962055..d4ecabd9080 100644 --- a/packages/rs-dpp/src/util/hash.rs +++ b/packages/rs-dpp/src/util/hash.rs @@ -9,6 +9,6 @@ pub fn hash(payload: impl AsRef<[u8]>) -> [u8; 32] { Sha256::digest(Sha256::digest(payload)).into() } -pub fn ripemd160_sha256(data: &[u8]) -> Vec { - ripemd160::Hash::hash(&sha256::Hash::hash(data)).to_vec() +pub fn ripemd160_sha256(data: &[u8]) -> [u8; 20] { + ripemd160::Hash::hash(&sha256::Hash::hash(data)).into_inner() } diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index e9d4576d8d1..cbeef09c1b8 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -34,6 +34,7 @@ use crate::abci::server::AbciApplication; use crate::error::execution::ExecutionError; +use crate::error::query::QueryError; use crate::error::Error; use crate::execution::block_proposal::BlockProposal; use crate::execution::engine::BlockExecutionOutcome; @@ -526,23 +527,35 @@ where } fn query(&self, request: RequestQuery) -> Result { - let RequestQuery { - data, path, prove, .. - } = request; + let RequestQuery { data, path, .. } = &request; - let result = self.platform.query(path.as_str(), data.as_slice(), prove)?; + let result = self.platform.query(path.as_str(), data.as_slice())?; - let (code, data) = if result.is_valid() { - (0, result.data.unwrap_or_default()) + let (code, data, log) = if result.is_valid() { + ( + 0, + result.data.unwrap_or_default(), + "query success".to_string(), + ) } else { - (1, vec![]) + let mut buffer: Vec = Vec::new(); + ciborium::ser::into_writer( + &result + .errors + .iter() + .map(|e| e.to_string()) + .collect::>(), + &mut buffer, + ) + .map_err(|e| e.to_string())?; + (1, buffer, format!("{:?}", result.errors)) }; - Ok(ResponseQuery { + let response = ResponseQuery { //todo: right now just put GRPC error codes, // later we will use own error codes code, - log: "".to_string(), + log, info: "".to_string(), index: 0, key: vec![], @@ -550,7 +563,10 @@ where proof_ops: None, height: self.platform.state.read().unwrap().height() as i64, codespace: "".to_string(), - }) + }; + tracing::trace!(method = "query", ?request, ?response); + + Ok(response) } } // diff --git a/packages/rs-drive-abci/src/abci/mimic.rs b/packages/rs-drive-abci/src/abci/mimic.rs index 1e29b124a13..327cef8ccd1 100644 --- a/packages/rs-drive-abci/src/abci/mimic.rs +++ b/packages/rs-drive-abci/src/abci/mimic.rs @@ -36,6 +36,8 @@ pub struct MimicExecuteBlockOutcome { pub withdrawal_transactions: Vec, /// The next validators hash pub next_validator_set_hash: Vec, + /// Root App hash + pub root_app_hash: [u8; 32], } /// Options for execution @@ -326,7 +328,7 @@ impl<'a, C: CoreRPCLike> AbciApplication<'a, C> { next_validators_hash: next_validator_set_hash.clone(), consensus_hash: [0; 32].to_vec(), next_consensus_hash: [0; 32].to_vec(), - app_hash, + app_hash: app_hash.clone(), results_hash: [0; 32].to_vec(), evidence_hash: vec![], proposed_app_version: 0, @@ -356,6 +358,9 @@ impl<'a, C: CoreRPCLike> AbciApplication<'a, C> { Ok(MimicExecuteBlockOutcome { withdrawal_transactions: withdrawals, next_validator_set_hash, + root_app_hash: app_hash + .try_into() + .expect("expected 32 bytes for the root hash"), }) } } diff --git a/packages/rs-drive-abci/src/error/query.rs b/packages/rs-drive-abci/src/error/query.rs index 1278678fb7a..b44f03e1a32 100644 --- a/packages/rs-drive-abci/src/error/query.rs +++ b/packages/rs-drive-abci/src/error/query.rs @@ -4,6 +4,7 @@ use drive::error::proof::ProofError; use drive::error::query::QuerySyntaxError as SyntaxError; use drive::error::Error as DriveError; use prost::DecodeError; +use tenderdash_abci::proto::abci::ResponseException; /// Errors #[derive(Debug, thiserror::Error)] @@ -31,3 +32,11 @@ pub enum QueryError { #[error("protobuf decoding error: {0}")] ProtobufDecode(#[from] DecodeError), } + +impl From for ResponseException { + fn from(value: QueryError) -> Self { + Self { + error: value.to_string(), + } + } +} diff --git a/packages/rs-drive-abci/src/query/mod.rs b/packages/rs-drive-abci/src/query/mod.rs index 8aff6efd0c9..e771be0fd1e 100644 --- a/packages/rs-drive-abci/src/query/mod.rs +++ b/packages/rs-drive-abci/src/query/mod.rs @@ -88,7 +88,6 @@ impl Platform { &self, query_path: &str, query_data: &[u8], - _prove: bool, ) -> Result>, Error> { let state = self.state.read().unwrap(); let metadata = ResponseMetadata { diff --git a/packages/rs-drive-abci/tests/strategy_tests/execution.rs b/packages/rs-drive-abci/tests/strategy_tests/execution.rs index d710cc97b5a..201ec592586 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/execution.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/execution.rs @@ -1,6 +1,7 @@ use crate::masternodes; use crate::masternodes::{GenerateTestMasternodeUpdates, MasternodeListItemWithUpdates}; use crate::operations::FinalizeBlockOperation::IdentityAddKeys; +use crate::query::ProofVerification; use crate::signer::SimpleSigner; use crate::strategy::{ ChainExecutionOutcome, ChainExecutionParameters, Strategy, StrategyRandomness, @@ -655,6 +656,7 @@ pub(crate) fn continue_chain_for_strategy( let MimicExecuteBlockOutcome { withdrawal_transactions: mut withdrawals_this_block, next_validator_set_hash, + root_app_hash, } = abci_app .mimic_execute_block( proposer.pro_tx_hash.into_inner(), @@ -692,6 +694,19 @@ pub(crate) fn continue_chain_for_strategy( current_time_ms += config.block_spacing_ms; + if let Some(query_strategy) = &strategy.query_testing { + query_strategy.query_chain_for_strategy( + &ProofVerification { + root_app_hash: &root_app_hash, + block_signature: &vec![], //todo + quorum_hash: ¤t_quorum_with_test_info.quorum_hash.into_inner(), + }, + ¤t_identities, + &abci_app, + StrategyRandomness::RNGEntropy(rng.clone()), + ) + } + let next_quorum_hash = QuorumHash::from_inner(next_validator_set_hash.try_into().unwrap()); if current_quorum_hash != next_quorum_hash { current_quorum_hash = next_quorum_hash; diff --git a/packages/rs-drive-abci/tests/strategy_tests/failures.rs b/packages/rs-drive-abci/tests/strategy_tests/failures.rs index 31502286923..d6a33499790 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/failures.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/failures.rs @@ -40,6 +40,7 @@ mod tests { deterministic_start_seed: Some(99), dont_finalize_block: true, }), + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 51fa103f268..314c6805d86 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -50,6 +50,7 @@ mod frequency; mod masternode_list_item_helpers; mod masternodes; mod operations; +mod query; mod signer; mod strategy; mod transitions; @@ -65,6 +66,7 @@ mod tests { use crate::operations::{ DocumentAction, DocumentOp, IdentityUpdateOp, Operation, OperationType, }; + use crate::query::QueryStrategy; use crate::strategy::MasternodeListChangesStrategy; use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::BlockHash; @@ -117,6 +119,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -163,6 +166,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -209,6 +213,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -301,6 +306,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -356,6 +362,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -402,6 +409,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: true, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -485,6 +493,7 @@ mod tests { }, rotate_quorums: true, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -550,6 +559,7 @@ mod tests { }, rotate_quorums: true, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -610,6 +620,7 @@ mod tests { }, rotate_quorums: true, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -691,6 +702,12 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: Some(QueryStrategy { + query_identities_by_public_key_hashes: Frequency { + times_per_block_range: 1..5, + chance_per_block: None, + }, + }), }; let config = PlatformConfig { verify_sum_trees: true, @@ -738,6 +755,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { @@ -797,6 +815,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -888,6 +907,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -973,6 +993,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -1038,6 +1059,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { @@ -1131,6 +1153,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { @@ -1224,6 +1247,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { @@ -1318,6 +1342,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let day_in_ms = 1000 * 60 * 60 * 24; @@ -1430,6 +1455,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let day_in_ms = 1000 * 60 * 60 * 24; @@ -1493,6 +1519,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -1563,6 +1590,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -1634,6 +1662,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, @@ -1716,6 +1745,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let config = PlatformConfig { verify_sum_trees: true, diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs new file mode 100644 index 00000000000..155c5650e43 --- /dev/null +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -0,0 +1,161 @@ +use crate::frequency::Frequency; +use crate::strategy::{ChainExecutionParameters, StrategyRandomness}; +use dapi_grpc::platform::v0::{ + GetIdentitiesByPublicKeyHashesRequest, GetIdentitiesByPublicKeyHashesResponse, +}; +use dpp::identity::{Identity, KeyID, PartialIdentity}; +use dpp::serialization_traits::PlatformDeserializable; +use drive::drive::verify::RootHash; +use drive::drive::Drive; +use drive_abci::abci::AbciApplication; +use drive_abci::config::PlatformConfig; +use drive_abci::rpc::core::MockCoreRPCLike; +use prost::Message; +use rand::prelude::SliceRandom; +use rand::rngs::StdRng; +use rand::{Rng, SeedableRng}; +use std::collections::{BTreeSet, HashMap, HashSet}; + +#[derive(Clone, Debug, Default)] +pub struct QueryStrategy { + pub query_identities_by_public_key_hashes: Frequency, +} + +#[derive(Debug)] +pub struct ProofVerification<'a> { + pub root_app_hash: &'a [u8; 32], + pub block_signature: &'a Vec, + pub quorum_hash: &'a [u8; 32], +} + +impl QueryStrategy { + pub(crate) fn query_chain_for_strategy( + &self, + proof_verification: &ProofVerification, + current_identities: &Vec, + abci_app: &AbciApplication, + seed: StrategyRandomness, + ) { + let mut rng = match seed { + StrategyRandomness::SeedEntropy(seed) => StdRng::seed_from_u64(seed), + StrategyRandomness::RNGEntropy(rng) => rng, + }; + let QueryStrategy { + query_identities_by_public_key_hashes, + } = self; + if query_identities_by_public_key_hashes.is_set() { + Self::query_identities_by_public_key_hashes( + proof_verification, + current_identities, + query_identities_by_public_key_hashes, + abci_app, + &mut rng, + ); + } + } + + pub(crate) fn query_identities_by_public_key_hashes( + proof_verification: &ProofVerification, + current_identities: &Vec, + frequency: &Frequency, + abci_app: &AbciApplication, + rng: &mut StdRng, + ) { + let events = frequency.events_if_hit(rng); + + for _i in 0..events { + let identity_count = rng.gen_range(1..10); + let chosen_identities = current_identities.choose_multiple(rng, identity_count); + let public_key_hashes = chosen_identities + .into_iter() + .filter_map(|identity| { + let unique_public_keys: Vec<_> = identity + .public_keys + .iter() + .filter(|(_, public_key)| public_key.key_type.is_unique_key_type()) + .collect(); + + if unique_public_keys.is_empty() { + None + } else { + let key_num = rng.gen_range(0..unique_public_keys.len()); + let public_key = unique_public_keys[key_num].1; + Some(( + public_key.hash().unwrap(), + identity.clone().into_partial_identity_info_no_balance(), + )) + } + }) + .collect::>(); + + let prove: bool = rng.gen(); + + let request = GetIdentitiesByPublicKeyHashesRequest { + public_key_hashes: public_key_hashes + .iter() + .map(|(hash, _)| hash.to_vec()) + .collect(), + prove, + }; + let encoded_request = request.encode_to_vec(); + let query_validation_result = abci_app + .platform + .query("/identities/by-public-key-hash", encoded_request.as_slice()) + .expect("expected to run query"); + + assert!( + query_validation_result.errors.is_empty(), + "{:?}", + query_validation_result.errors + ); + + let query_data = query_validation_result + .into_data() + .expect("expected data on query_validation_result"); + let response = GetIdentitiesByPublicKeyHashesResponse::decode(query_data.as_slice()) + .expect("expected to deserialize"); + if prove { + let proof = response.proof.expect("expect to receive proof back"); + let (proof_root_hash, identities): (RootHash, HashMap<[u8; 20], Option>) = + Drive::verify_full_identities_by_public_key_hashes( + &proof.grovedb_proof, + public_key_hashes + .keys() + .cloned() + .collect::>() + .as_slice(), + ) + .expect("expected to verify proof"); + let identities: HashMap<[u8; 20], PartialIdentity> = identities + .into_iter() + .map(|(k, v)| { + ( + k, + v.expect("expect an identity") + .into_partial_identity_info_no_balance(), + ) + }) + .collect(); + assert_eq!(proof_verification.root_app_hash, &proof_root_hash); + assert_eq!(identities, public_key_hashes); + } else { + let identities_returned = response + .identities + .into_iter() + .map(|serialized| { + Identity::deserialize(&serialized) + .expect("expected to deserialize identity") + .id + }) + .collect::>(); + assert_eq!( + identities_returned, + public_key_hashes + .values() + .map(|partial_identity| partial_identity.id) + .collect() + ); + } + } + } +} diff --git a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs index 58d8fa1e2ff..dd77fc966c5 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs @@ -4,6 +4,7 @@ use crate::operations::FinalizeBlockOperation::IdentityAddKeys; use crate::operations::{ DocumentAction, DocumentOp, FinalizeBlockOperation, IdentityUpdateOp, Operation, OperationType, }; +use crate::query::QueryStrategy; use crate::signer::SimpleSigner; use crate::BlockHeight; use dashcore_rpc::dashcore; @@ -121,6 +122,7 @@ pub struct Strategy { pub proposer_strategy: MasternodeListChangesStrategy, pub rotate_quorums: bool, pub failure_testing: Option, + pub query_testing: Option, } #[derive(Clone, Debug)] diff --git a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs index a7e318dd320..c71970e62c0 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs @@ -35,6 +35,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let twenty_minutes_in_ms = 1000 * 60 * 20; let mut config = PlatformConfig { @@ -272,6 +273,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { @@ -499,6 +501,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let hour_in_ms = 1000 * 60 * 60; let mut config = PlatformConfig { @@ -658,6 +661,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let block_start = platform @@ -816,6 +820,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { @@ -909,6 +914,7 @@ mod tests { proposer_strategy: Default::default(), rotate_quorums: false, failure_testing: None, + query_testing: None, }; // we hit the required threshold to upgrade diff --git a/packages/rs-drive/src/error/proof.rs b/packages/rs-drive/src/error/proof.rs index ec386023934..9a1e63f3284 100644 --- a/packages/rs-drive/src/error/proof.rs +++ b/packages/rs-drive/src/error/proof.rs @@ -36,3 +36,15 @@ pub enum ProofError { actual: Path, }, } + +fn get_error_code(error: &ProofError) -> u32 { + match error { + ProofError::TooManyElements(_) => 6000, + ProofError::WrongElementCount(_) => 6001, + ProofError::Overflow(_) => 6002, + ProofError::CorruptedProof(_) => 6003, + ProofError::IncompleteProof(_) => 6004, + ProofError::IncorrectValueSize(_) => 6005, + ProofError::IncorrectElementPath { .. } => 6006, + } +} diff --git a/packages/rs-platform-value/src/types/binary_data.rs b/packages/rs-platform-value/src/types/binary_data.rs index 87a9272f2ed..cd42cd415c4 100644 --- a/packages/rs-platform-value/src/types/binary_data.rs +++ b/packages/rs-platform-value/src/types/binary_data.rs @@ -171,6 +171,18 @@ impl From<&BinaryData> for String { } } +impl PartialEq<&[u8; 20]> for BinaryData { + fn eq(&self, other: &&[u8; 20]) -> bool { + self.as_slice() == *other + } +} + +impl PartialEq<[u8; 20]> for BinaryData { + fn eq(&self, other: &[u8; 20]) -> bool { + self.as_slice() == *other + } +} + impl PartialEq<&[u8]> for BinaryData { fn eq(&self, other: &&[u8]) -> bool { self.as_slice() == *other diff --git a/packages/wasm-dpp/src/identity/identity_public_key/mod.rs b/packages/wasm-dpp/src/identity/identity_public_key/mod.rs index 92500dd1604..a5b40bd35dd 100644 --- a/packages/wasm-dpp/src/identity/identity_public_key/mod.rs +++ b/packages/wasm-dpp/src/identity/identity_public_key/mod.rs @@ -122,7 +122,7 @@ impl IdentityPublicKeyWasm { #[wasm_bindgen(js_name=hash)] pub fn hash(&self) -> Result, JsValue> { - self.0.hash().with_js_error() + self.0.hash().map(|result| result.to_vec()).with_js_error() } #[wasm_bindgen(js_name=isMaster)]