|
|
@ -1,5 +1,5 @@ |
|
|
|
use super::{
|
|
|
|
super::{super::ONE, Felt, MerkleStore, WORD_SIZE, ZERO},
|
|
|
|
super::{super::ONE, empty_roots::EMPTY_WORD, Felt, MerkleStore, WORD_SIZE, ZERO},
|
|
|
|
EmptySubtreeRoots, InnerNodeInfo, NodeIndex, Rpo256, RpoDigest, TieredSmt, Vec, Word,
|
|
|
|
};
|
|
|
|
|
|
|
@ -587,6 +587,154 @@ fn tsmt_bottom_tier_two() { |
|
|
|
assert_eq!(leaves.next(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
// GET PROOF TESTS
|
|
|
|
// ================================================================================================
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn tsmt_get_proof() {
|
|
|
|
let mut smt = TieredSmt::default();
|
|
|
|
|
|
|
|
// --- insert a value into the tree ---------------------------------------
|
|
|
|
let raw_a = 0b_01010101_01010101_11111111_11111111_10110101_10101010_11111100_00000000_u64;
|
|
|
|
let key_a = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw_a)]);
|
|
|
|
let value_a = [ONE, ONE, ONE, ONE];
|
|
|
|
smt.insert(key_a, value_a);
|
|
|
|
|
|
|
|
// --- insert a value with the same 48-bit prefix into the tree -----------
|
|
|
|
let raw_b = 0b_01010101_01010101_11111111_11111111_10110101_10101010_10111100_00000000_u64;
|
|
|
|
let key_b = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw_b)]);
|
|
|
|
let value_b = [ONE, ONE, ONE, ZERO];
|
|
|
|
smt.insert(key_b, value_b);
|
|
|
|
|
|
|
|
let smt_alt = smt.clone();
|
|
|
|
|
|
|
|
// --- insert a value with the same 32-bit prefix into the tree -----------
|
|
|
|
let raw_c = 0b_01010101_01010101_11111111_11111111_11111101_10101010_10111100_00000000_u64;
|
|
|
|
let key_c = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw_c)]);
|
|
|
|
let value_c = [ONE, ONE, ZERO, ZERO];
|
|
|
|
smt.insert(key_c, value_c);
|
|
|
|
|
|
|
|
// --- insert a value with the same 64-bit prefix as A into the tree ------
|
|
|
|
let raw_d = 0b_01010101_01010101_11111111_11111111_10110101_10101010_11111100_00000000_u64;
|
|
|
|
let key_d = RpoDigest::from([ZERO, ZERO, ONE, Felt::new(raw_d)]);
|
|
|
|
let value_d = [ONE, ZERO, ZERO, ZERO];
|
|
|
|
smt.insert(key_d, value_d);
|
|
|
|
|
|
|
|
// at this point the tree looks as follows:
|
|
|
|
// - A and D are located in the same node at depth 64.
|
|
|
|
// - B is located at depth 64 and shares the same 48-bit prefix with A and D.
|
|
|
|
// - C is located at depth 48 and shares the same 32-bit prefix with A, B, and D.
|
|
|
|
|
|
|
|
// --- generate proof for key A and test that it verifies correctly -------
|
|
|
|
let proof = smt.prove(key_a);
|
|
|
|
assert!(proof.verify_membership(&key_a, &value_a, &smt.root()));
|
|
|
|
|
|
|
|
assert!(!proof.verify_membership(&key_a, &value_b, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_a, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_b, &value_a, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_a, &value_a, &smt_alt.root()));
|
|
|
|
|
|
|
|
assert_eq!(proof.get(&key_a), Some(value_a));
|
|
|
|
assert_eq!(proof.get(&key_b), None);
|
|
|
|
|
|
|
|
// since A and D are stored in the same node, we should be able to use the proof to verify
|
|
|
|
// membership of D
|
|
|
|
assert!(proof.verify_membership(&key_d, &value_d, &smt.root()));
|
|
|
|
assert_eq!(proof.get(&key_d), Some(value_d));
|
|
|
|
|
|
|
|
// --- generate proof for key B and test that it verifies correctly -------
|
|
|
|
let proof = smt.prove(key_b);
|
|
|
|
assert!(proof.verify_membership(&key_b, &value_b, &smt.root()));
|
|
|
|
|
|
|
|
assert!(!proof.verify_membership(&key_b, &value_a, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_b, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_a, &value_b, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_b, &value_b, &smt_alt.root()));
|
|
|
|
|
|
|
|
assert_eq!(proof.get(&key_b), Some(value_b));
|
|
|
|
assert_eq!(proof.get(&key_a), None);
|
|
|
|
|
|
|
|
// --- generate proof for key C and test that it verifies correctly -------
|
|
|
|
let proof = smt.prove(key_c);
|
|
|
|
assert!(proof.verify_membership(&key_c, &value_c, &smt.root()));
|
|
|
|
|
|
|
|
assert!(!proof.verify_membership(&key_c, &value_a, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_c, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_a, &value_c, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_c, &value_c, &smt_alt.root()));
|
|
|
|
|
|
|
|
assert_eq!(proof.get(&key_c), Some(value_c));
|
|
|
|
assert_eq!(proof.get(&key_b), None);
|
|
|
|
|
|
|
|
// --- generate proof for key D and test that it verifies correctly -------
|
|
|
|
let proof = smt.prove(key_d);
|
|
|
|
assert!(proof.verify_membership(&key_d, &value_d, &smt.root()));
|
|
|
|
|
|
|
|
assert!(!proof.verify_membership(&key_d, &value_b, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_d, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_b, &value_d, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key_d, &value_d, &smt_alt.root()));
|
|
|
|
|
|
|
|
assert_eq!(proof.get(&key_d), Some(value_d));
|
|
|
|
assert_eq!(proof.get(&key_b), None);
|
|
|
|
|
|
|
|
// since A and D are stored in the same node, we should be able to use the proof to verify
|
|
|
|
// membership of A
|
|
|
|
assert!(proof.verify_membership(&key_a, &value_a, &smt.root()));
|
|
|
|
assert_eq!(proof.get(&key_a), Some(value_a));
|
|
|
|
|
|
|
|
// --- generate proof for an empty key at depth 64 ------------------------
|
|
|
|
// this key has the same 48-bit prefix as A but is different from B
|
|
|
|
let raw = 0b_01010101_01010101_11111111_11111111_10110101_10101010_11111100_00000011_u64;
|
|
|
|
let key = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)]);
|
|
|
|
|
|
|
|
let proof = smt.prove(key);
|
|
|
|
assert!(proof.verify_membership(&key, &EMPTY_WORD, &smt.root()));
|
|
|
|
|
|
|
|
assert!(!proof.verify_membership(&key, &value_a, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key, &EMPTY_WORD, &smt_alt.root()));
|
|
|
|
|
|
|
|
assert_eq!(proof.get(&key), Some(EMPTY_WORD));
|
|
|
|
assert_eq!(proof.get(&key_b), None);
|
|
|
|
|
|
|
|
// the same proof should verify against any key with the same 64-bit prefix
|
|
|
|
let key2 = RpoDigest::from([ONE, ONE, ZERO, Felt::new(raw)]);
|
|
|
|
assert!(proof.verify_membership(&key2, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert_eq!(proof.get(&key2), Some(EMPTY_WORD));
|
|
|
|
|
|
|
|
// but verifying if against a key with the same 63-bit prefix (or smaller) should fail
|
|
|
|
let raw3 = 0b_01010101_01010101_11111111_11111111_10110101_10101010_11111100_00000010_u64;
|
|
|
|
let key3 = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw3)]);
|
|
|
|
assert!(!proof.verify_membership(&key3, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert_eq!(proof.get(&key3), None);
|
|
|
|
|
|
|
|
// --- generate proof for an empty key at depth 48 ------------------------
|
|
|
|
// this key has the same 32-prefix as A, B, C, and D, but is different from C
|
|
|
|
let raw = 0b_01010101_01010101_11111111_11111111_00110101_10101010_11111100_00000000_u64;
|
|
|
|
let key = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)]);
|
|
|
|
|
|
|
|
let proof = smt.prove(key);
|
|
|
|
assert!(proof.verify_membership(&key, &EMPTY_WORD, &smt.root()));
|
|
|
|
|
|
|
|
assert!(!proof.verify_membership(&key, &value_a, &smt.root()));
|
|
|
|
assert!(!proof.verify_membership(&key, &EMPTY_WORD, &smt_alt.root()));
|
|
|
|
|
|
|
|
assert_eq!(proof.get(&key), Some(EMPTY_WORD));
|
|
|
|
assert_eq!(proof.get(&key_b), None);
|
|
|
|
|
|
|
|
// the same proof should verify against any key with the same 48-bit prefix
|
|
|
|
let raw2 = 0b_01010101_01010101_11111111_11111111_00110101_10101010_01111100_00000000_u64;
|
|
|
|
let key2 = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw2)]);
|
|
|
|
assert!(proof.verify_membership(&key2, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert_eq!(proof.get(&key2), Some(EMPTY_WORD));
|
|
|
|
|
|
|
|
// but verifying against a key with the same 47-bit prefix (or smaller) should fail
|
|
|
|
let raw3 = 0b_01010101_01010101_11111111_11111111_00110101_10101011_11111100_00000000_u64;
|
|
|
|
let key3 = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw3)]);
|
|
|
|
assert!(!proof.verify_membership(&key3, &EMPTY_WORD, &smt.root()));
|
|
|
|
assert_eq!(proof.get(&key3), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ERROR TESTS
|
|
|
|
// ================================================================================================
|
|
|
|
|
|
|
|