diff --git a/Cargo.lock b/Cargo.lock index 8ee9c7c2ac..754666c08a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,18 +451,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] -name = "bitcoin-private" -version = "0.1.0" +name = "bitcoin-io" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" [[package]] name = "bitcoin_hashes" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" dependencies = [ - "bitcoin-private", + "bitcoin-io", + "hex-conservative", ] [[package]] @@ -1145,7 +1146,7 @@ dependencies = [ [[package]] name = "dashcore" version = "0.30.0" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#a29315dbe56729be1be963fb6f7b60a22288663f" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.31.0#003b1aed973be7eb98591c6ec3c8f82eafab4645" dependencies = [ "anyhow", "bech32", @@ -1161,12 +1162,12 @@ dependencies = [ [[package]] name = "dashcore-private" version = "0.1.0" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#a29315dbe56729be1be963fb6f7b60a22288663f" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.31.0#003b1aed973be7eb98591c6ec3c8f82eafab4645" [[package]] name = "dashcore-rpc" -version = "0.15.2" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.4#bd6efdb850151f1dcd8e3f38d4796d18c5be518c" +version = "0.15.7" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.7#3a16a75496939e6855fc9c823a4d5de11c2f0ee8" dependencies = [ "dashcore-private", "dashcore-rpc-json", @@ -1180,8 +1181,8 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" -version = "0.15.2" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.4#bd6efdb850151f1dcd8e3f38d4796d18c5be518c" +version = "0.15.7" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.7#3a16a75496939e6855fc9c823a4d5de11c2f0ee8" dependencies = [ "bincode", "dashcore", @@ -1195,10 +1196,9 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.12.0" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#a29315dbe56729be1be963fb6f7b60a22288663f" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.31.0#003b1aed973be7eb98591c6ec3c8f82eafab4645" dependencies = [ "dashcore-private", - "rs-x11-hash", "secp256k1", "serde", ] @@ -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" @@ -2209,6 +2216,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -2446,12 +2462,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 +2798,7 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "indexmap 2.4.0", + "indexmap 2.6.0", "ipnet", "metrics", "metrics-util", @@ -3260,7 +3276,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 +3354,7 @@ dependencies = [ "bs58", "ciborium 0.2.0", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "lazy_static", "platform-serialization", "platform-version", @@ -3875,17 +3891,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rs-x11-hash" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ea852806513d6f5fd7750423300375bc8481a18ed033756c1a836257893a30" -dependencies = [ - "bindgen 0.65.1", - "cc", - "libc", -] - [[package]] name = "rust_decimal" version = "1.36.0" @@ -4055,9 +4060,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "secp256k1" -version = "0.27.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", "rand", @@ -4067,9 +4072,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ "cc", ] @@ -4148,7 +4153,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 +4228,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.4.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -4861,7 +4866,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 +4877,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 +4888,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 +4949,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 +5715,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.4.0", + "indexmap 2.6.0", "memchr", "thiserror", "zopfli", diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 4d7d1c79d9..8d6e3c93c5 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -29,7 +29,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "serde", -], default-features = false, branch = "master" } +], default-features = false, tag = "0.31.0" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4" } diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index dfcd0e0e25..b9a1eda906 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -28,7 +28,7 @@ rand = "0.8.5" tempfile = "3.3.0" hex = "0.4.3" indexmap = { version = "2.2.6", features = ["serde"] } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.4" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.7" } dpp = { path = "../rs-dpp", features = ["abci"] } simple-signer = { path = "../simple-signer" } rust_decimal = "1.2.5" 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/Cargo.toml b/packages/rs-sdk/Cargo.toml index dcce9de6fb..992a4a9b1d 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -33,7 +33,7 @@ envy = { version = "0.4.2", optional = true } futures = { version = "0.3.30" } derive_more = { version = "1.0", features = ["from"] } # dashcore-rpc is only needed for core rpc; TODO remove once we have correct core rpc impl -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.4" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.7" } lru = { version = "0.12.3", optional = true } bip37-bloom-filter = { git = "https://github.com/dashpay/rs-bip37-bloom-filter", branch = "develop" } zeroize = { version = "1.8", features = ["derive"] } 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(); diff --git a/packages/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index aaa449c293..29f0989df0 100644 --- a/packages/simple-signer/Cargo.toml +++ b/packages/simple-signer/Cargo.toml @@ -8,6 +8,6 @@ rust-version.workspace = true [dependencies] bincode = { version = "2.0.0-rc.3", features = ["serde"] } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.4" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.7" } dpp = { path = "../rs-dpp", features = ["abci"] } base64 = { version = "0.22.1" }