Skip to content

Commit 3ced8ea

Browse files
committed
add non-existence proofs documentation in the mdbook, mv EMPTY->EMPTY_VALUE & NULL->EMPTY_HASH
1 parent 5ecf161 commit 3ced8ea

File tree

8 files changed

+30
-31
lines changed

8 files changed

+30
-31
lines changed

book/src/merkletree.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ Since leaf positions are deterministic based on the key, the same approach is us
137137

138138
For the current use cases, we don't need to prove that the key exists but the value is different on that leaf, so we only use the option 1.
139139

140+
There are 2 cases to have into account when dealing with non-inclusion proofs:
141+
- case i) the expected leaf does not exist.
142+
- case ii) the expected leaf does exist in the tree, but it has a different `key`.
143+
140144

141145
## Encoding
142146
> TODO: how key-values, nodes, merkle-proofs, ... are encoded.

src/backends/plonky2/basetypes.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ pub type Proof = Plonky2Proof<F, PoseidonGoldilocksConfig, D>;
3030
pub const HASH_SIZE: usize = 4;
3131
pub const VALUE_SIZE: usize = 4;
3232

33-
// TODO mv `EMPTY`-> `EMTPY_VALUE`, and `NULL` -> `EMPTY_HASH`.
34-
pub const EMPTY: Value = Value([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
33+
pub const EMPTY_VALUE: Value = Value([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
3534
pub const SELF_ID_HASH: Hash = Hash([F::ONE, F::ZERO, F::ZERO, F::ZERO]);
36-
pub const NULL: Hash = Hash([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
35+
pub const EMPTY_HASH: Hash = Hash([F::ZERO, F::ZERO, F::ZERO, F::ZERO]);
3736

3837
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
3938
pub struct Value(pub [F; VALUE_SIZE]);

src/backends/plonky2/mock_signed.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub mod tests {
110110
use super::*;
111111
use crate::constants::MAX_DEPTH;
112112
use crate::frontend;
113-
use crate::middleware::{self, F, NULL};
113+
use crate::middleware::{self, EMPTY_HASH, F};
114114

115115
#[test]
116116
fn test_mock_signed_0() -> Result<()> {
@@ -137,7 +137,7 @@ pub mod tests {
137137
assert!(!bad_pod.verify());
138138

139139
let mut bad_pod = pod.clone();
140-
let bad_kv = (hash_str(KEY_SIGNER).into(), Value(PodId(NULL).0 .0));
140+
let bad_kv = (hash_str(KEY_SIGNER).into(), Value(PodId(EMPTY_HASH).0 .0));
141141
let bad_kvs_mt = &bad_pod
142142
.kvs()
143143
.into_iter()

src/backends/plonky2/primitives/merkletree.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fmt;
77
use std::iter::IntoIterator;
88

99
use crate::backends::counter;
10-
use crate::backends::plonky2::basetypes::{hash_fields, Hash, Value, F, NULL};
10+
use crate::backends::plonky2::basetypes::{hash_fields, Hash, Value, EMPTY_HASH, F};
1111

1212
// mod merkletree_circuit;
1313
pub use super::merkletree_circuit::*;
@@ -182,7 +182,7 @@ impl MerkleTree {
182182
pub fn kv_hash(key: &Value, value: Option<Value>) -> Hash {
183183
value
184184
.map(|v| hash_fields(&[key.0.to_vec(), v.0.to_vec(), vec![GoldilocksField(1)]].concat()))
185-
.unwrap_or(NULL)
185+
.unwrap_or(EMPTY_HASH)
186186
}
187187

188188
impl<'a> IntoIterator for &'a MerkleTree {
@@ -305,14 +305,14 @@ impl Node {
305305
}
306306
fn compute_hash(&mut self) -> Hash {
307307
match self {
308-
Self::None => NULL,
308+
Self::None => EMPTY_HASH,
309309
Self::Leaf(l) => l.compute_hash(),
310310
Self::Intermediate(n) => n.compute_hash(),
311311
}
312312
}
313313
fn hash(&self) -> Hash {
314314
match self {
315-
Self::None => NULL,
315+
Self::None => EMPTY_HASH,
316316
Self::Leaf(l) => l.hash(),
317317
Self::Intermediate(n) => n.hash(),
318318
}
@@ -475,8 +475,8 @@ impl Intermediate {
475475
}
476476
fn compute_hash(&mut self) -> Hash {
477477
if self.left.clone().is_empty() && self.right.clone().is_empty() {
478-
self.hash = Some(NULL);
479-
return NULL;
478+
self.hash = Some(EMPTY_HASH);
479+
return EMPTY_HASH;
480480
}
481481
let l_hash = self.left.compute_hash();
482482
let r_hash = self.right.compute_hash();

src/backends/plonky2/primitives/merkletree_circuit.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use std::iter::IntoIterator;
2424

2525
use crate::backends::counter;
2626
use crate::backends::plonky2::basetypes::{
27-
hash_fields, Hash, Value, D, EMPTY, F, HASH_SIZE, NULL, VALUE_SIZE,
27+
hash_fields, Hash, Value, D, EMPTY_HASH, EMPTY_VALUE, F, HASH_SIZE, VALUE_SIZE,
2828
};
2929
use crate::backends::plonky2::primitives::merkletree::MerkleProof;
3030

@@ -34,7 +34,6 @@ pub struct MerkleProofCircuit<const MAX_DEPTH: usize> {
3434
value: Vec<Target>,
3535
existence: BoolTarget,
3636
siblings: Vec<HashOutTarget>,
37-
// siblings_selectors: Vec<BoolTarget>,
3837
case_ii_selector: BoolTarget, // for case ii)
3938
other_key: Vec<Target>,
4039
other_value: Vec<Target>,
@@ -49,7 +48,7 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
4948
let value = builder.add_virtual_targets(VALUE_SIZE);
5049
// from proof struct:
5150
let existence = builder.add_virtual_bool_target_safe();
52-
// siblings are padded
51+
// siblings are padded till MAX_DEPTH length
5352
let siblings = builder.add_virtual_hashes(MAX_DEPTH);
5453

5554
let case_ii_selector = builder.add_virtual_bool_target_safe();
@@ -102,7 +101,7 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
102101

103102
// if we're in the case i), use leaf_hash=EMPTY_HASH, else use the
104103
// previously computed hash h.
105-
let empty_hash = builder.constant_hash(HashOut::from(NULL.0));
104+
let empty_hash = builder.constant_hash(HashOut::from(EMPTY_HASH.0));
106105
let leaf_hash = HashOutTarget::from_vec(
107106
(0..4)
108107
.map(|j| builder.select(case_i_selector, empty_hash.elements[j], h.elements[j]))
@@ -115,10 +114,7 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
115114
// compute the root for the given siblings and the computed leaf_hash
116115
// (this is for the three cases (existence, non-existence case i, and
117116
// non-existence case ii)
118-
let computed_root = Self::compute_root_from_leaf(
119-
builder, &path, &leaf_hash, &siblings,
120-
// &siblings_selectors,
121-
)?;
117+
let computed_root = Self::compute_root_from_leaf(builder, &path, &leaf_hash, &siblings)?;
122118
// ensure that the computed root matches the given root (which is a
123119
// public input)
124120
builder.connect_hashes(computed_root, root);
@@ -152,7 +148,7 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
152148

153149
// pad siblings with zeros to length MAX_DEPTH
154150
let mut siblings = proof.siblings.clone();
155-
siblings.resize(MAX_DEPTH, NULL);
151+
siblings.resize(MAX_DEPTH, EMPTY_HASH);
156152
assert_eq!(self.siblings.len(), siblings.len());
157153

158154
for (i, sibling) in siblings.iter().enumerate() {
@@ -167,8 +163,8 @@ impl<const MAX_DEPTH: usize> MerkleProofCircuit<MAX_DEPTH> {
167163
} else {
168164
// existence & non-existence case i) expected leaf does not exist
169165
pw.set_bool_target(self.case_ii_selector, false)?;
170-
pw.set_target_arr(&self.other_key, &EMPTY.0.to_vec())?;
171-
pw.set_target_arr(&self.other_value, &EMPTY.0.to_vec())?;
166+
pw.set_target_arr(&self.other_key, &EMPTY_VALUE.0.to_vec())?;
167+
pw.set_target_arr(&self.other_value, &EMPTY_VALUE.0.to_vec())?;
172168
}
173169

174170
Ok(())
@@ -408,7 +404,7 @@ pub mod tests {
408404
(key, value, proof)
409405
} else {
410406
let key = Value::from(hash_value(&Value::from(200)));
411-
(key, EMPTY, tree.prove_nonexistence(&key)?)
407+
(key, EMPTY_VALUE, tree.prove_nonexistence(&key)?)
412408
};
413409
assert_eq!(proof.existence, existence);
414410

@@ -473,7 +469,7 @@ pub mod tests {
473469
tree.prove(&key)?
474470
} else {
475471
let proof = tree.prove_nonexistence(&key)?;
476-
(EMPTY, proof)
472+
(EMPTY_VALUE, proof)
477473
};
478474

479475
assert_eq!(proof.existence, contains);

src/middleware/basetypes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@
3535
/// then the Value, Hash and F types would come from the plonky3 backend.
3636
#[cfg(feature = "backend_plonky2")]
3737
pub use crate::backends::plonky2::basetypes::{
38-
hash_fields, hash_str, hash_value, Hash, Value, EMPTY, F, HASH_SIZE, NULL, SELF_ID_HASH,
39-
VALUE_SIZE,
38+
hash_fields, hash_str, hash_value, Hash, Value, EMPTY_HASH, EMPTY_VALUE, F, HASH_SIZE,
39+
SELF_ID_HASH, VALUE_SIZE,
4040
};

src/middleware/containers.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::constants::MAX_DEPTH;
88
#[cfg(feature = "backend_plonky2")]
99
use crate::backends::plonky2::primitives::merkletree::{Iter as TreeIter, MerkleProof, MerkleTree};
1010

11-
use super::basetypes::{hash_value, Hash, Value, EMPTY};
11+
use super::basetypes::{hash_value, Hash, Value, EMPTY_VALUE};
1212

1313
/// Dictionary: the user original keys and values are hashed to be used in the leaf.
1414
/// leaf.key=hash(original_key)
@@ -78,7 +78,7 @@ impl Set {
7878
.iter()
7979
.map(|e| {
8080
let h = hash_value(e);
81-
(Value::from(h), EMPTY)
81+
(Value::from(h), EMPTY_VALUE)
8282
})
8383
.collect();
8484
Ok(Self {
@@ -99,7 +99,7 @@ impl Set {
9999
self.mt.prove_nonexistence(value)
100100
}
101101
pub fn verify(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
102-
MerkleTree::verify(MAX_DEPTH, root, proof, value, &EMPTY)
102+
MerkleTree::verify(MAX_DEPTH, root, proof, value, &EMPTY_VALUE)
103103
}
104104
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
105105
MerkleTree::verify_nonexistence(MAX_DEPTH, root, proof, value)

src/middleware/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl fmt::Display for PodId {
2323
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2424
if *self == SELF {
2525
write!(f, "self")
26-
} else if self.0 == NULL {
26+
} else if self.0 == EMPTY_HASH {
2727
write!(f, "null")
2828
} else {
2929
write!(f, "{}", self.0)
@@ -185,7 +185,7 @@ impl Pod for NonePod {
185185
true
186186
}
187187
fn id(&self) -> PodId {
188-
PodId(NULL)
188+
PodId(EMPTY_HASH)
189189
}
190190
fn pub_statements(&self) -> Vec<Statement> {
191191
Vec::new()

0 commit comments

Comments
 (0)