Skip to content

Commit 6388718

Browse files
committed
fix(sdk): into_option() should return Some() for proof of non-existence
1 parent 405e4d6 commit 6388718

File tree

2 files changed

+62
-21
lines changed

2 files changed

+62
-21
lines changed

packages/rs-drive-proof-verifier/src/proof.rs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ impl FromProof<platform::GetDataContractsRequest> for DataContracts {
832832
})?;
833833

834834
verify_tenderdash_proof(proof, mtd, &root_hash, provider)?;
835-
let maybe_contracts = contracts
835+
let contracts = contracts
836836
.into_iter()
837837
.map(|(k, v)| {
838838
Identifier::from_bytes(&k).map(|id| (id, v)).map_err(|e| {
@@ -841,8 +841,13 @@ impl FromProof<platform::GetDataContractsRequest> for DataContracts {
841841
}
842842
})
843843
})
844-
.collect::<Result<DataContracts, Error>>()?
845-
.into_option();
844+
.collect::<Result<DataContracts, Error>>()?;
845+
846+
let maybe_contracts = if contracts.is_empty() {
847+
None
848+
} else {
849+
Some(contracts)
850+
};
846851

847852
Ok((maybe_contracts, mtd.clone(), proof.clone()))
848853
}
@@ -1376,8 +1381,7 @@ impl FromProof<platform::GetContestedResourcesRequest> for ContestedResources {
13761381

13771382
verify_tenderdash_proof(proof, mtd, &root_hash, provider)?;
13781383

1379-
let resources: ContestedResources =
1380-
items.into_iter().map(|v| ContestedResource(v)).collect();
1384+
let resources: ContestedResources = items.into_iter().map(ContestedResource).collect();
13811385

13821386
Ok((resources.into_option(), mtd.clone(), proof.clone()))
13831387
}
@@ -1849,6 +1853,8 @@ fn u32_to_u16_opt(i: u32) -> Result<Option<u16>, Error> {
18491853
pub trait Length {
18501854
/// Return number of non-None elements in the data structure
18511855
fn count_some(&self) -> usize;
1856+
/// Return number of all elements in the data structure, including None
1857+
fn count(&self) -> usize;
18521858
}
18531859

18541860
impl<T: Length> Length for Option<T> {
@@ -1858,30 +1864,52 @@ impl<T: Length> Length for Option<T> {
18581864
Some(i) => i.count_some(),
18591865
}
18601866
}
1867+
fn count(&self) -> usize {
1868+
match self {
1869+
None => 0,
1870+
Some(i) => i.count(),
1871+
}
1872+
}
18611873
}
18621874

18631875
impl<T> Length for Vec<Option<T>> {
18641876
fn count_some(&self) -> usize {
18651877
self.iter().filter(|v| v.is_some()).count()
18661878
}
1879+
1880+
fn count(&self) -> usize {
1881+
self.len()
1882+
}
18671883
}
18681884

18691885
impl<K, T> Length for Vec<(K, Option<T>)> {
18701886
fn count_some(&self) -> usize {
18711887
self.iter().filter(|(_, v)| v.is_some()).count()
18721888
}
1889+
1890+
fn count(&self) -> usize {
1891+
self.len()
1892+
}
18731893
}
18741894

18751895
impl<K, T> Length for BTreeMap<K, Option<T>> {
18761896
fn count_some(&self) -> usize {
18771897
self.values().filter(|v| v.is_some()).count()
18781898
}
1899+
1900+
fn count(&self) -> usize {
1901+
self.len()
1902+
}
18791903
}
18801904

18811905
impl<K, T> Length for IndexMap<K, Option<T>> {
18821906
fn count_some(&self) -> usize {
18831907
self.values().filter(|v| v.is_some()).count()
18841908
}
1909+
1910+
fn count(&self) -> usize {
1911+
self.len()
1912+
}
18851913
}
18861914

18871915
/// Implement Length trait for a type
@@ -1891,16 +1919,24 @@ impl<K, T> Length for IndexMap<K, Option<T>> {
18911919
/// * `$object`: The type for which to implement Length trait
18921920
/// * `$len`: A closure that returns the length of the object; if ommitted, defaults to 1
18931921
macro_rules! define_length {
1894-
($object:ty,$len:expr) => {
1922+
($object:ty,$some:expr,$counter:expr) => {
18951923
impl Length for $object {
18961924
fn count_some(&self) -> usize {
18971925
#[allow(clippy::redundant_closure_call)]
1898-
$len(self)
1926+
$some(self)
1927+
}
1928+
1929+
fn count(&self) -> usize {
1930+
#[allow(clippy::redundant_closure_call)]
1931+
$counter(self)
18991932
}
19001933
}
19011934
};
1935+
($object:ty,$some:expr) => {
1936+
define_length!($object, $some, $some);
1937+
};
19021938
($object:ty) => {
1903-
define_length!($object, |_| 1);
1939+
define_length!($object, |_| 1, |_| 1);
19041940
};
19051941
}
19061942

@@ -1910,22 +1946,30 @@ define_length!(Document);
19101946
define_length!(Identity);
19111947
define_length!(IdentityBalance);
19121948
define_length!(IdentityBalanceAndRevision);
1913-
define_length!(IdentitiesContractKeys, |x: &IdentitiesContractKeys| x
1914-
.values()
1915-
.map(|v| v.count_some())
1916-
.sum());
1949+
define_length!(
1950+
IdentitiesContractKeys,
1951+
|x: &IdentitiesContractKeys| x.values().map(|v| v.count_some()).sum(),
1952+
|x: &IdentitiesContractKeys| x.len()
1953+
);
19171954
define_length!(ContestedResources, |x: &ContestedResources| x.0.len());
19181955
define_length!(Contenders, |x: &Contenders| x.contenders.len());
19191956
define_length!(Voters, |x: &Voters| x.0.len());
19201957
define_length!(
19211958
VotePollsGroupedByTimestamp,
1922-
|x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum()
1959+
|x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum(),
1960+
|x: &VotePollsGroupedByTimestamp| x.0.len()
19231961
);
1962+
1963+
/// Convert a type into an Option
19241964
trait IntoOption
19251965
where
19261966
Self: Sized,
19271967
{
1928-
/// For zero-length data structures, return None, otherwise return Some(self)
1968+
/// For zero-length data structures, return None, otherwise return Some(self).
1969+
///
1970+
/// In case of a zero-length data structure, the function returns None.
1971+
/// Otherwise, it returns Some(self), even it all values are None. This is to ensure that proof of absence
1972+
/// preserves the keys that are not present in the data structure.
19291973
fn into_option(self) -> Option<Self>;
19301974
}
19311975

@@ -1934,7 +1978,7 @@ impl<L: Length> IntoOption for L {
19341978
where
19351979
Self: Sized,
19361980
{
1937-
if self.count_some() == 0 {
1981+
if self.count() == 0 {
19381982
None
19391983
} else {
19401984
Some(self)

packages/rs-drive-proof-verifier/src/types.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ pub type RetrievedObjects<K, O> = IndexMap<K, Option<O>>;
8181
/// order of objects returned by Dash Drive, which is not always guaranteed to be correct.
8282
/// You can sort the objects by key if you need a specific order; see [`IndexMap::sort_keys`] and similar methods.
8383
///
84-
/// The ordering of the objects is guaranteed to be the same as the order of objects returned by Dash Drive.
85-
///
8684
/// # Generic Type Parameters
8785
///
8886
/// * `K`: The type of the keys in the map.
@@ -254,10 +252,9 @@ impl ContestedResource {
254252
)
255253
}
256254
}
257-
258-
impl Into<Value> for ContestedResource {
259-
fn into(self) -> Value {
260-
self.0
255+
impl From<ContestedResource> for Value {
256+
fn from(resource: ContestedResource) -> Self {
257+
resource.0
261258
}
262259
}
263260

0 commit comments

Comments
 (0)