Skip to content

Commit

Permalink
ics23: return value alongside a (non-)existence proof (#91)
Browse files Browse the repository at this point in the history
* ics23: `get_with_ics23_proof` return value side-by-side a (non-)existence proof

* cargo: bump major version

* ics23: enshrine new api in tests

* ics23: fix typo
  • Loading branch information
erwanor authored Apr 14, 2023
1 parent 521fcab commit 3ca6066
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jmt"
version = "0.4.2"
version = "0.5.0"
authors = [
"Penumbra Labs <[email protected]>",
"Diem Association <[email protected]>",
Expand Down
53 changes: 38 additions & 15 deletions src/tree/ics23_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use crate::{
storage::HasPreimage,
storage::TreeReader,
tree::ExclusionProof,
JellyfishMerkleTree, KeyHash, SimpleHasher, Version, SPARSE_MERKLE_PLACEHOLDER_HASH,
JellyfishMerkleTree, KeyHash, OwnedValue, SimpleHasher, Version,
SPARSE_MERKLE_PLACEHOLDER_HASH,
};

fn sparse_merkle_proof_to_ics23_existence_proof<H: SimpleHasher>(
Expand Down Expand Up @@ -185,12 +186,14 @@ where
}
}

/// Returns the value and an [`JMTProof`].
/// Returns the value corresponding to the specified key (if there is a value associated with it)
/// along with an [ics23::CommitmentProof] proving either the presence of the value at that key,
/// or the absence of any value at that key, depending on which is the case.
pub fn get_with_ics23_proof(
&self,
key: Vec<u8>,
version: Version,
) -> Result<ics23::CommitmentProof> {
) -> Result<(Option<OwnedValue>, ics23::CommitmentProof)> {
let key_hash: KeyHash = KeyHash::with::<H>(key.as_slice());
let proof_or_exclusion = self.get_with_exclusion_proof(key_hash, version)?;

Expand All @@ -199,9 +202,12 @@ where
let ics23_exist =
sparse_merkle_proof_to_ics23_existence_proof(key, value.clone(), &proof);

Ok(ics23::CommitmentProof {
proof: Some(ics23::commitment_proof::Proof::Exist(ics23_exist)),
})
Ok((
Some(value),
ics23::CommitmentProof {
proof: Some(ics23::commitment_proof::Proof::Exist(ics23_exist)),
},
))
}
Err(exclusion_proof) => {
let ics23_nonexist = self.exclusion_proof_to_ics23_nonexistence_proof(
Expand All @@ -210,9 +216,12 @@ where
&exclusion_proof,
)?;

Ok(ics23::CommitmentProof {
proof: Some(ics23::commitment_proof::Proof::Nonexist(ics23_nonexist)),
})
Ok((
None,
ics23::CommitmentProof {
proof: Some(ics23::commitment_proof::Proof::Nonexist(ics23_nonexist)),
},
))
}
}
}
Expand Down Expand Up @@ -288,7 +297,8 @@ mod tests {
let (new_root_hash, batch) = tree.put_value_set(kvs, 0).unwrap();
db.write_tree_update_batch(batch).unwrap();

let commitment_proof = tree.get_with_ics23_proof(b"notexist".to_vec(), 0).unwrap();
let (value_retrieved, commitment_proof) =
tree.get_with_ics23_proof(b"notexist".to_vec(), 0).unwrap();

let key_hash = KeyHash::with::<Sha256>(b"notexist".as_slice());
let proof_or_exclusion = tree.get_with_exclusion_proof(key_hash, 0).unwrap();
Expand All @@ -313,7 +323,9 @@ mod tests {
&ics23_spec(),
&new_root_hash.0.to_vec(),
b"notexist"
))
));

assert_eq!(value_retrieved, None)
}
Rightmost {
rightmost_left_proof,
Expand All @@ -331,7 +343,9 @@ mod tests {
&ics23_spec(),
&new_root_hash.0.to_vec(),
b"notexist"
))
));

assert_eq!(value_retrieved, None)
}
Middle {
leftmost_right_proof,
Expand All @@ -358,7 +372,9 @@ mod tests {
&ics23_spec(),
&new_root_hash.0.to_vec(),
b"notexist"
))
));

assert_eq!(value_retrieved, None)
}
},
}
Expand Down Expand Up @@ -392,7 +408,8 @@ mod tests {
let (new_root_hash, batch) = tree.put_value_set(kvs, 0).unwrap();
db.write_tree_update_batch(batch).unwrap();

let commitment_proof = tree.get_with_ics23_proof(b"key".to_vec(), 0).unwrap();
let (value_retrieved, commitment_proof) =
tree.get_with_ics23_proof(b"key".to_vec(), 0).unwrap();

assert!(ics23::verify_membership::<HostFunctionsManager>(
&commitment_proof,
Expand All @@ -401,6 +418,8 @@ mod tests {
b"key",
b"value",
));

assert_eq!(value_retrieved.unwrap(), b"value");
}

#[test]
Expand All @@ -419,7 +438,9 @@ mod tests {
db.write_tree_update_batch(batch).unwrap();
}

let commitment_proof = tree
let value_maxversion = format!("value{}", MAX_VERSION).into_bytes();

let (value_retrieved, commitment_proof) = tree
.get_with_ics23_proof(format!("key{}", MAX_VERSION).into_bytes(), MAX_VERSION)
.unwrap();

Expand All @@ -432,5 +453,7 @@ mod tests {
format!("key{}", MAX_VERSION).as_bytes(),
format!("value{}", MAX_VERSION).as_bytes(),
));

assert_eq!(value_retrieved.unwrap(), value_maxversion);
}
}

0 comments on commit 3ca6066

Please sign in to comment.