From 908d0b31ac4e93109957f162dc044b7541c77827 Mon Sep 17 00:00:00 2001 From: lklimek <842586+lklimek@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:08:36 +0200 Subject: [PATCH] fix(sdk)!: wrong order of objects returned by Drive (#2207) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Cargo.lock | 45 +++--- packages/rs-drive-proof-verifier/Cargo.toml | 2 + packages/rs-drive-proof-verifier/src/proof.rs | 138 ++++++++++++------ .../rs-drive-proof-verifier/src/provider.rs | 2 +- packages/rs-drive-proof-verifier/src/types.rs | 47 +++--- .../rs-drive-proof-verifier/src/unproved.rs | 2 +- packages/rs-sdk/src/mock/requests.rs | 37 ++++- packages/rs-sdk/src/platform/fetch_many.rs | 3 +- packages/rs-sdk/tests/fetch/data_contract.rs | 7 +- packages/rs-sdk/tests/fetch/document.rs | 3 +- packages/rs-sdk/tests/fetch/epoch.rs | 12 +- .../rs-sdk/tests/fetch/mock_fetch_many.rs | 7 +- 12 files changed, 200 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ee9c7c2ac..518b077b81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1376,7 +1376,7 @@ dependencies = [ "env_logger 0.11.5", "getrandom", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "itertools 0.13.0", "json-schema-compatibility-validator", @@ -1429,7 +1429,7 @@ dependencies = [ "grovedb-storage", "grovedb-version", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "intmap", "itertools 0.13.0", @@ -1472,7 +1472,7 @@ dependencies = [ "envy", "file-rotate", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "itertools 0.13.0", "lazy_static", @@ -1512,6 +1512,7 @@ dependencies = [ "dpp", "drive", "hex", + "indexmap 2.6.0", "platform-serialization", "platform-serialization-derive", "serde", @@ -1988,7 +1989,7 @@ dependencies = [ "grovedbg-types", "hex", "hex-literal", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "intmap", "itertools 0.12.1", @@ -2045,7 +2046,7 @@ dependencies = [ "grovedb-version", "grovedb-visualize", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "num_cpus", "rand", @@ -2121,7 +2122,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.4.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2163,6 +2164,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -2446,12 +2453,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "serde", ] @@ -2782,7 +2789,7 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "indexmap 2.4.0", + "indexmap 2.6.0", "ipnet", "metrics", "metrics-util", @@ -3260,7 +3267,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.4.0", + "indexmap 2.6.0", ] [[package]] @@ -3338,7 +3345,7 @@ dependencies = [ "bs58", "ciborium 0.2.0", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "lazy_static", "platform-serialization", "platform-version", @@ -4148,7 +4155,7 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3b863381a05ffefbc82571a2d893edf47b27fb0ebedbf582c39640e51abebef" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "itoa", "memchr", "ryu", @@ -4223,7 +4230,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.4.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -4861,7 +4868,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "toml_datetime", "winnow 0.5.40", ] @@ -4872,7 +4879,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "toml_datetime", "winnow 0.5.40", ] @@ -4883,7 +4890,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -4944,7 +4951,7 @@ source = "git+https://github.com/QuantumExplorer/tower?branch=fix/indexMap2OnV04 dependencies = [ "futures-core", "futures-util", - "indexmap 2.4.0", + "indexmap 2.6.0", "pin-project", "pin-project-lite", "rand", @@ -5710,7 +5717,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.4.0", + "indexmap 2.6.0", "memchr", "thiserror", "zopfli", diff --git a/packages/rs-drive-proof-verifier/Cargo.toml b/packages/rs-drive-proof-verifier/Cargo.toml index baee7efa93..f46f844629 100644 --- a/packages/rs-drive-proof-verifier/Cargo.toml +++ b/packages/rs-drive-proof-verifier/Cargo.toml @@ -15,6 +15,7 @@ mocks = [ "dep:platform-serialization-derive", "dep:platform-serialization", "dpp/document-serde-conversion", + "indexmap/serde", ] [dependencies] @@ -42,4 +43,5 @@ serde_json = { version = "1.0.103", features = [ "preserve_order", ], optional = true } hex = { version = "0.4.3" } +indexmap = { version = "2.6.0" } derive_more = { version = "1.0", features = ["from"] } diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index 0d7b23e05d..3685df1779 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -43,6 +43,7 @@ use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVot use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQuery; use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery; use drive::query::{DriveDocumentQuery, VotePollsByEndDateDriveQuery}; +use indexmap::IndexMap; use std::array::TryFromSliceError; use std::collections::BTreeMap; use std::num::TryFromIntError; @@ -831,25 +832,22 @@ impl FromProof for DataContracts { })?; verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - - let maybe_contracts: Option>> = - if !contracts.is_empty() { - let contracts: DataContracts = contracts - .into_iter() - .try_fold(DataContracts::new(), |mut acc, (k, v)| { - Identifier::from_bytes(&k).map(|id| { - acc.insert(id, v); - acc - }) - }) - .map_err(|e| Error::ResultEncodingError { + let contracts = contracts + .into_iter() + .map(|(k, v)| { + Identifier::from_bytes(&k).map(|id| (id, v)).map_err(|e| { + Error::ResultEncodingError { error: e.to_string(), - })?; + } + }) + }) + .collect::>()?; - Some(contracts) - } else { - None - }; + let maybe_contracts = if contracts.is_empty() { + None + } else { + Some(contracts) + }; Ok((maybe_contracts, mtd.clone(), proof.clone())) } @@ -904,7 +902,11 @@ impl FromProof for DataContractHistory verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - Ok((maybe_history, mtd.clone(), proof.clone())) + Ok(( + maybe_history.map(IndexMap::from_iter), + mtd.clone(), + proof.clone(), + )) } } @@ -987,13 +989,13 @@ impl FromProof for ExtendedEpochInfo { provider, )?; - if let Some(mut e) = epochs.0 { + if let Some(e) = epochs.0 { if e.len() != 1 { return Err(Error::RequestError { error: format!("expected 1 epoch, got {}", e.len()), }); } - let epoch = e.pop_first().and_then(|v| v.1); + let epoch = e.into_iter().next().and_then(|v| v.1); Ok((epoch, epochs.1, epochs.2)) } else { Ok((None, epochs.1, epochs.2)) @@ -1056,7 +1058,7 @@ impl FromProof for ExtendedEpochInfos { (info.index, Some(v)) }) - .collect::>>(); + .collect::(); verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; @@ -1203,10 +1205,11 @@ impl FromProof for Elements { let (root_hash, objects) = Drive::verify_elements(&proof.grovedb_proof, path, keys, platform_version)?; + let elements: Elements = Elements::from_iter(objects); verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - Ok((objects.into_option(), mtd.clone(), proof.clone())) + Ok((elements.into_option(), mtd.clone(), proof.clone())) } } @@ -1378,8 +1381,7 @@ impl FromProof for ContestedResources { verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - let resources: ContestedResources = - items.into_iter().map(|v| ContestedResource(v)).collect(); + let resources: ContestedResources = items.into_iter().map(ContestedResource).collect(); Ok((resources.into_option(), mtd.clone(), proof.clone())) } @@ -1638,23 +1640,25 @@ impl FromProof for Vote { } }; - let (mut maybe_votes, mtd, proof) = - ResourceVotesByIdentity::maybe_from_proof_with_metadata( - request, - response, - network, - platform_version, - provider, - )?; + let (maybe_votes, mtd, proof) = ResourceVotesByIdentity::maybe_from_proof_with_metadata( + request, + response, + network, + platform_version, + provider, + )?; - let (id, vote) = match maybe_votes.as_mut() { + let (id, vote) = match maybe_votes { Some(v) if v.len() > 1 => { return Err(Error::ResponseDecodeError { error: format!("expected 1 vote, got {}", v.len()), }) } Some(v) if v.is_empty() => return Ok((None, mtd, proof)), - Some(v) => v.pop_first().expect("is_empty() must detect empty map"), + Some(v) => v + .into_iter() + .next() + .expect("is_empty() must detect empty map"), None => return Ok((None, mtd, proof)), }; @@ -1849,6 +1853,8 @@ fn u32_to_u16_opt(i: u32) -> Result, Error> { pub trait Length { /// Return number of non-None elements in the data structure fn count_some(&self) -> usize; + /// Return number of all elements in the data structure, including None + fn count(&self) -> usize; } impl Length for Option { @@ -1858,24 +1864,52 @@ impl Length for Option { Some(i) => i.count_some(), } } + fn count(&self) -> usize { + match self { + None => 0, + Some(i) => i.count(), + } + } } impl Length for Vec> { fn count_some(&self) -> usize { self.iter().filter(|v| v.is_some()).count() } + + fn count(&self) -> usize { + self.len() + } } impl Length for Vec<(K, Option)> { fn count_some(&self) -> usize { self.iter().filter(|(_, v)| v.is_some()).count() } + + fn count(&self) -> usize { + self.len() + } } impl Length for BTreeMap> { fn count_some(&self) -> usize { self.values().filter(|v| v.is_some()).count() } + + fn count(&self) -> usize { + self.len() + } +} + +impl Length for IndexMap> { + fn count_some(&self) -> usize { + self.values().filter(|v| v.is_some()).count() + } + + fn count(&self) -> usize { + self.len() + } } /// Implement Length trait for a type @@ -1885,16 +1919,24 @@ impl Length for BTreeMap> { /// * `$object`: The type for which to implement Length trait /// * `$len`: A closure that returns the length of the object; if ommitted, defaults to 1 macro_rules! define_length { - ($object:ty,$len:expr) => { + ($object:ty,$some:expr,$counter:expr) => { impl Length for $object { fn count_some(&self) -> usize { #[allow(clippy::redundant_closure_call)] - $len(self) + $some(self) + } + + fn count(&self) -> usize { + #[allow(clippy::redundant_closure_call)] + $counter(self) } } }; + ($object:ty,$some:expr) => { + define_length!($object, $some, $some); + }; ($object:ty) => { - define_length!($object, |_| 1); + define_length!($object, |_| 1, |_| 1); }; } @@ -1904,22 +1946,30 @@ define_length!(Document); define_length!(Identity); define_length!(IdentityBalance); define_length!(IdentityBalanceAndRevision); -define_length!(IdentitiesContractKeys, |x: &IdentitiesContractKeys| x - .values() - .map(|v| v.count_some()) - .sum()); +define_length!( + IdentitiesContractKeys, + |x: &IdentitiesContractKeys| x.values().map(|v| v.count_some()).sum(), + |x: &IdentitiesContractKeys| x.len() +); define_length!(ContestedResources, |x: &ContestedResources| x.0.len()); define_length!(Contenders, |x: &Contenders| x.contenders.len()); define_length!(Voters, |x: &Voters| x.0.len()); define_length!( VotePollsGroupedByTimestamp, - |x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum() + |x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum(), + |x: &VotePollsGroupedByTimestamp| x.0.len() ); + +/// Convert a type into an Option trait IntoOption where Self: Sized, { - /// For zero-length data structures, return None, otherwise return Some(self) + /// For zero-length data structures, return None, otherwise return Some(self). + /// + /// In case of a zero-length data structure, the function returns None. + /// Otherwise, it returns Some(self), even it all values are None. This is to ensure that proof of absence + /// preserves the keys that are not present in the data structure. fn into_option(self) -> Option; } @@ -1928,7 +1978,7 @@ impl IntoOption for L { where Self: Sized, { - if self.count_some() == 0 { + if self.count() == 0 { None } else { Some(self) diff --git a/packages/rs-drive-proof-verifier/src/provider.rs b/packages/rs-drive-proof-verifier/src/provider.rs index ecead85994..e7eafd2e45 100644 --- a/packages/rs-drive-proof-verifier/src/provider.rs +++ b/packages/rs-drive-proof-verifier/src/provider.rs @@ -47,7 +47,7 @@ pub trait ContextProvider: Send + Sync { /// # Returns /// /// * `Ok(Option>)`: On success, returns the data contract if it exists, or `None` if it does not. - /// We use Arc to avoid copying the data contract. + /// We use Arc to avoid copying the data contract. /// * `Err(Error)`: On failure, returns an error indicating why the operation failed. fn get_data_contract( &self, diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index a40fefb98c..40fa528a54 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -31,6 +31,8 @@ use dpp::{ }; use drive::grovedb::query_result_type::Path; use drive::grovedb::Element; +// IndexMap is exposed to the public API +pub use indexmap::IndexMap; use std::collections::{BTreeMap, BTreeSet}; #[cfg(feature = "mocks")] @@ -49,36 +51,46 @@ pub use evonode_status::*; /// from a server using [`FetchMany`](dash_sdk::platform::FetchMany) or parsing a proof that contains multiple objects /// using [`FromProof`](crate::FromProof). /// -/// Each key in the `RetrievedObjects` corresponds to an object of generic type `O`. -/// If an object is found for a given key, the value is `Some(object)`. -/// If no object is found for a given key, the value is `None`. +/// Each key `K` in the `RetrievedObjects` corresponds to zero or one object of generic type `O`: +/// * if an object is found for a given key, the value is `Some(object)`, +/// * if no object is found for a given key, the value is `None`; this can be interpreted as a proof of absence. +/// +/// This data structure preserves order of objects insertion. However, actual order of objects depends on the order of +/// objects returned by Dash Drive, which is not always guaranteed to be correct. +/// You can sort the objects by key if you need a specific order; see [`IndexMap::sort_keys`] and similar methods. +/// +/// `RetrievedObjects` is a wrapper around the [`IndexMap`] type. /// /// # Generic Type Parameters /// /// * `K`: The type of the keys in the map. /// * `O`: The type of the objects in the map. -pub type RetrievedObjects = BTreeMap>; +pub type RetrievedObjects = IndexMap>; -/// A data structure that holds a set of objects of a generic type `O`, indexed by a key of type `K`. +/// A data structure that holds a set of values of a generic type `I`, indexed by a key of type `K`. /// /// This type is typically returned by functions that operate on multiple objects, such as fetching multiple objects /// from a server using [`FetchMany`](dash_sdk::platform::FetchMany) or parsing a proof that contains multiple objects /// using [`FromProof`](crate::FromProof). /// -/// Each key in the `RetrievedObjects` corresponds to an object of generic type `O`. -/// If a value is found for a given key, the value is `value`. -/// If no value is found for a given key, the value is `0`. +/// Each key in this data structure corresponds to an existing value of generic type `I`. It differs from +/// [`RetrievedObjects`] in that it does not contain `Option`, but only `I`, so it cannot be interpreted as a +/// proof of absence. +/// +/// This data structure preserves the order of object insertion. However, the actual order of objects depends on the +/// order of objects returned by Dash Drive, which is not always guaranteed to be correct. +/// You can sort the objects by key if you need a specific order; see [`IndexMap::sort_keys`] and similar methods. /// /// # Generic Type Parameters /// /// * `K`: The type of the keys in the map. -/// * `I`: The type of the integer in the map. -pub type RetrievedIntegerValue = BTreeMap; +/// * `I`: The type of the integer values in the map. +pub type RetrievedValues = IndexMap; /// History of a data contract. /// /// Contains a map of data contract revisions to data contracts. -pub type DataContractHistory = BTreeMap; +pub type DataContractHistory = RetrievedValues; /// Multiple data contracts. /// /// Mapping between data contract IDs and data contracts. @@ -240,10 +252,9 @@ impl ContestedResource { ) } } - -impl Into for ContestedResource { - fn into(self) -> Value { - self.0 +impl From for Value { + fn from(resource: ContestedResource) -> Self { + resource.0 } } @@ -561,7 +572,7 @@ pub type MasternodeProtocolVotes = RetrievedObjects); +pub struct ProposerBlockCounts(pub RetrievedValues); impl FromIterator<(ProTxHash, Option)> for ProposerBlockCounts { fn from_iter)>>( @@ -575,7 +586,7 @@ impl FromIterator<(ProTxHash, Option)> for ProposerBl let identifier = Identifier::from(pro_tx_hash.to_byte_array()); // Adjust this conversion logic as needed (identifier, block_count) }) - .collect::>(); + .collect::>(); ProposerBlockCounts(map) } @@ -593,7 +604,7 @@ impl FromIterator<(ProTxHash, Option)> for ProposerBlock let identifier = Identifier::from(pro_tx_hash.to_byte_array()); // Adjust this conversion logic as needed (identifier, block_count) }) - .collect::>(); + .collect::>(); ProposerBlockCounts(map) } diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs index bc2f2e9e51..cc7c63c83e 100644 --- a/packages/rs-drive-proof-verifier/src/unproved.rs +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -218,7 +218,7 @@ impl FromUnproved for CurrentQuorumsInfo let mut quorum_hash = [0u8; 32]; quorum_hash.copy_from_slice(&vs.quorum_hash); - // Parse ValidatorV0 members into a BTreeMap + // Parse ValidatorV0 members let members = vs .members .into_iter() diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 0b2e43692f..582c3628a0 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -3,7 +3,7 @@ use dpp::bincode::config::standard; use dpp::{ bincode, block::extended_epoch_info::ExtendedEpochInfo, - dashcore::{hashes::Hash, ProTxHash}, + dashcore::{hashes::Hash as CoreHash, ProTxHash}, document::{serialization_traits::DocumentCborMethodsV0, Document}, identifier::Identifier, identity::IdentityPublicKey, @@ -18,11 +18,11 @@ use dpp::{ use drive::grovedb::Element; use drive_proof_verifier::types::{ Contenders, ContestedResources, CurrentQuorumsInfo, ElementFetchRequestItem, EvoNodeStatus, - IdentityBalanceAndRevision, MasternodeProtocolVote, PrefundedSpecializedBalance, - ProposerBlockCounts, RetrievedIntegerValue, TotalCreditsInPlatform, - VotePollsGroupedByTimestamp, Voters, + IdentityBalanceAndRevision, IndexMap, MasternodeProtocolVote, PrefundedSpecializedBalance, + ProposerBlockCounts, RetrievedValues, TotalCreditsInPlatform, VotePollsGroupedByTimestamp, + Voters, }; -use std::collections::BTreeMap; +use std::{collections::BTreeMap, hash::Hash}; static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); @@ -115,6 +115,29 @@ impl MockResponse for BTreeMap { } } +impl MockResponse for IndexMap { + fn mock_deserialize(sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self + where + Self: Sized, + { + let (data, _): (IndexMap, Vec>, _) = + bincode::serde::decode_from_slice(buf, BINCODE_CONFIG).expect("decode IndexMap"); + + data.into_iter() + .map(|(k, v)| (K::mock_deserialize(sdk, &k), V::mock_deserialize(sdk, &v))) + .collect() + } + + fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec { + let data: IndexMap, Vec> = self + .iter() + .map(|(k, v)| (k.mock_serialize(sdk), v.mock_serialize(sdk))) + .collect(); + + bincode::serde::encode_to_vec(data, BINCODE_CONFIG).expect("encode IndexMap") + } +} + /// Serialize and deserialize the object for mocking using bincode. /// /// Use this macro when the object implements platform serialization. @@ -232,7 +255,7 @@ impl MockResponse for ProTxHash { { let data = platform_versioned_decode_from_slice(buf, BINCODE_CONFIG, sdk.version()) .expect("decode ProTxHash"); - ProTxHash::from_raw_hash(Hash::from_byte_array(data)) + ProTxHash::from_raw_hash(CoreHash::from_byte_array(data)) } } @@ -245,7 +268,7 @@ impl MockResponse for ProposerBlockCounts { where Self: Sized, { - let data = RetrievedIntegerValue::::mock_deserialize(sdk, buf); + let data = RetrievedValues::::mock_deserialize(sdk, buf); ProposerBlockCounts(data) } } diff --git a/packages/rs-sdk/src/platform/fetch_many.rs b/packages/rs-sdk/src/platform/fetch_many.rs index eede165d26..4ecf6e42cc 100644 --- a/packages/rs-sdk/src/platform/fetch_many.rs +++ b/packages/rs-sdk/src/platform/fetch_many.rs @@ -41,7 +41,6 @@ use drive_proof_verifier::types::{ }; use drive_proof_verifier::{types::Documents, FromProof}; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; -use std::collections::BTreeMap; /// Fetch multiple objects from Platform. /// @@ -239,7 +238,7 @@ impl FetchMany for Document { tracing::trace!(request=?document_query, response=?response, "fetch multiple documents"); // let object: Option> = sdk - let documents: BTreeMap> = sdk + let documents: Documents = sdk .parse_proof::(document_query, response) .await? .unwrap_or_default(); diff --git a/packages/rs-sdk/tests/fetch/data_contract.rs b/packages/rs-sdk/tests/fetch/data_contract.rs index b59acbb97a..adddd35cd6 100644 --- a/packages/rs-sdk/tests/fetch/data_contract.rs +++ b/packages/rs-sdk/tests/fetch/data_contract.rs @@ -145,6 +145,11 @@ async fn test_data_contract_history_read() { let result = DataContractHistory::fetch(&sdk, LimitQuery::from((id, 10))).await; assert!(matches!(result, Ok(Some(_))), "result: {:?}", result); - let (_, contract) = result.unwrap().unwrap().pop_first().unwrap(); + let (_, contract) = result + .expect("request should succeed") + .expect("data contract should exist") + .into_iter() + .next() + .expect("data contract"); assert_eq!(contract.id(), id); } diff --git a/packages/rs-sdk/tests/fetch/document.rs b/packages/rs-sdk/tests/fetch/document.rs index 8263250d0b..088cf73136 100644 --- a/packages/rs-sdk/tests/fetch/document.rs +++ b/packages/rs-sdk/tests/fetch/document.rs @@ -34,7 +34,8 @@ async fn document_read() { let first_doc = Document::fetch_many(&sdk, all_docs_query) .await .expect("fetch many documents") - .pop_first() + .into_iter() + .next() .expect("first item must exist") .1 .expect("document must exist"); diff --git a/packages/rs-sdk/tests/fetch/epoch.rs b/packages/rs-sdk/tests/fetch/epoch.rs index 8080e3b344..0c8f429d7f 100644 --- a/packages/rs-sdk/tests/fetch/epoch.rs +++ b/packages/rs-sdk/tests/fetch/epoch.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeMap; - use super::{common::setup_logs, config::Config}; use dapi_grpc::platform::{ v0::{get_identity_request::GetIdentityRequestV0, GetIdentityRequest}, @@ -15,6 +13,7 @@ use dash_sdk::{ use dpp::block::epoch::EpochIndex; use dpp::block::extended_epoch_info::v0::ExtendedEpochInfoV0Getters; use dpp::block::extended_epoch_info::ExtendedEpochInfo; +use drive_proof_verifier::types::ExtendedEpochInfos; use rs_dapi_client::{DapiRequestExecutor, RequestSettings}; /// Get current epoch index from DAPI response metadata @@ -35,7 +34,7 @@ async fn get_current_epoch(sdk: &Sdk, cfg: &Config) -> EpochIndex { } /// Check some assertions on returned epochs list fn assert_epochs( - epochs: BTreeMap>, + epochs: ExtendedEpochInfos, starting_epoch: EpochIndex, current_epoch: EpochIndex, limit: u16, @@ -89,10 +88,9 @@ async fn test_epoch_list() { let current_epoch = get_current_epoch(&sdk, &cfg).await; // When we fetch epochs from the server, starting with `starting_epoch` - let epochs: BTreeMap> = - ExtendedEpochInfo::fetch_many(&sdk, starting_epoch) - .await - .expect("list epochs"); + let epochs: ExtendedEpochInfos = ExtendedEpochInfo::fetch_many(&sdk, starting_epoch) + .await + .expect("list epochs"); assert_epochs( epochs, diff --git a/packages/rs-sdk/tests/fetch/mock_fetch_many.rs b/packages/rs-sdk/tests/fetch/mock_fetch_many.rs index fdf3811d8d..36bce78543 100644 --- a/packages/rs-sdk/tests/fetch/mock_fetch_many.rs +++ b/packages/rs-sdk/tests/fetch/mock_fetch_many.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeMap; - use super::common::{mock_data_contract, mock_document_type}; use dash_sdk::{ platform::{DocumentQuery, FetchMany}, @@ -14,6 +12,7 @@ use dpp::{ }, document::{Document, DocumentV0Getters}, }; +use drive_proof_verifier::types::Documents; /// Given some data contract, document type and 1 document of this type, when I request multiple documents, I get that /// document. @@ -26,13 +25,13 @@ async fn test_mock_document_fetch_many() { let expected_doc = document_type .random_document(None, sdk.version()) .expect("document should be created"); - let expected = BTreeMap::from([(expected_doc.id(), Some(expected_doc.clone()))]); + let expected = Documents::from([(expected_doc.id(), Some(expected_doc.clone()))]); // document that should not be returned, as it will be defined as a duplicate let not_expected_doc = document_type .random_document(None, sdk.version()) .expect("document 2 should be created"); - let not_expected = BTreeMap::from([(not_expected_doc.id(), Some(not_expected_doc))]); + let not_expected = Documents::from([(not_expected_doc.id(), Some(not_expected_doc))]); let document_type_name = document_type.name();