Remove max_depth in native MerkleTree (#442)
This simplifies the MerkleTree (and container) API. Defer the max depth check when assigning the witness (merkle proof siblings) to the merkle tree circuit. In this implementation the native Merkle Tree branches grow as much as they needed. There are no checks of max depth in the merkle tree. All keys are 256 bits (I added a debug_assert for this); so in the worst case a path will have depth 256. It can't have a longer depth because the `insert` method calls `prove_nonexistence` which errors if the key already exists; another one may exist which must be different and thus require a path <= 256 depth. Resolve #436
This commit is contained in:
parent
32dc85471d
commit
813a86c670
18 changed files with 266 additions and 462 deletions
|
|
@ -35,7 +35,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mock_prover = MockProver {};
|
let mock_prover = MockProver {};
|
||||||
let real_prover = Prover {};
|
let real_prover = Prover {};
|
||||||
let (vd_set, prover): (_, &dyn MainPodProver) = if mock {
|
let (vd_set, prover): (_, &dyn MainPodProver) = if mock {
|
||||||
(&VDSet::new(8, &[])?, &mock_prover)
|
(&VDSet::new(&[]), &mock_prover)
|
||||||
} else {
|
} else {
|
||||||
println!("Prebuilding circuits to calculate vd_set...");
|
println!("Prebuilding circuits to calculate vd_set...");
|
||||||
let vd_set = &*DEFAULT_VD_SET;
|
let vd_set = &*DEFAULT_VD_SET;
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Value::from)
|
.map(Value::from)
|
||||||
.collect();
|
.collect();
|
||||||
builder.insert(
|
builder.insert("friends", Set::new(friends_set));
|
||||||
"friends",
|
|
||||||
Set::new(params.max_merkle_proofs_containers, friends_set)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sign the dict and verify it
|
// Sign the dict and verify it
|
||||||
let signed_dict = builder.sign(&signer)?;
|
let signed_dict = builder.sign(&signer)?;
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,8 @@ pub static DEFAULT_VD_LIST: LazyLock<Vec<VerifierOnlyCircuitData>> = LazyLock::n
|
||||||
});
|
});
|
||||||
|
|
||||||
pub static DEFAULT_VD_SET: LazyLock<VDSet> = LazyLock::new(|| {
|
pub static DEFAULT_VD_SET: LazyLock<VDSet> = LazyLock::new(|| {
|
||||||
let params = Params::default();
|
|
||||||
let vds = &*DEFAULT_VD_LIST;
|
let vds = &*DEFAULT_VD_LIST;
|
||||||
VDSet::new(params.max_depth_mt_vds, vds).unwrap()
|
VDSet::new(vds)
|
||||||
});
|
});
|
||||||
|
|
||||||
/// VDSet is the set of the allowed verifier_data hashes. When proving a
|
/// VDSet is the set of the allowed verifier_data hashes. When proving a
|
||||||
|
|
@ -84,35 +83,29 @@ pub struct VDSet {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
#[schemars(skip)]
|
#[schemars(skip)]
|
||||||
proofs_map: HashMap<Hash, MerkleClaimAndProof>,
|
proofs_map: HashMap<Hash, MerkleClaimAndProof>,
|
||||||
tree_depth: usize,
|
|
||||||
vds_hashes: Vec<Hash>,
|
vds_hashes: Vec<Hash>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for VDSet {
|
impl PartialEq for VDSet {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.root == other.root
|
self.root == other.root && self.vds_hashes == other.vds_hashes
|
||||||
&& self.tree_depth == other.tree_depth
|
|
||||||
&& self.vds_hashes == other.vds_hashes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Eq for VDSet {}
|
impl Eq for VDSet {}
|
||||||
|
|
||||||
impl VDSet {
|
impl VDSet {
|
||||||
fn new_from_vds_hashes(tree_depth: usize, mut vds_hashes: Vec<Hash>) -> Result<Self> {
|
fn new_from_vds_hashes(mut vds_hashes: Vec<Hash>) -> Self {
|
||||||
// before using the hash values, sort them, so that each set of
|
// before using the hash values, sort them, so that each set of
|
||||||
// verifier_datas gets the same VDSet root
|
// verifier_datas gets the same VDSet root
|
||||||
vds_hashes.sort();
|
vds_hashes.sort();
|
||||||
|
|
||||||
let array = Array::new(
|
let array = Array::new(vds_hashes.iter().map(|vd| Value::from(*vd)).collect());
|
||||||
tree_depth,
|
|
||||||
vds_hashes.iter().map(|vd| Value::from(*vd)).collect(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let root = array.commitment();
|
let root = array.commitment();
|
||||||
let mut proofs_map = HashMap::<Hash, MerkleClaimAndProof>::new();
|
let mut proofs_map = HashMap::<Hash, MerkleClaimAndProof>::new();
|
||||||
|
|
||||||
for (i, vd) in vds_hashes.iter().enumerate() {
|
for (i, vd) in vds_hashes.iter().enumerate() {
|
||||||
let (value, proof) = array.prove(i)?;
|
let (value, proof) = array.prove(i).expect("exists");
|
||||||
let p = MerkleClaimAndProof {
|
let p = MerkleClaimAndProof {
|
||||||
root,
|
root,
|
||||||
key: RawValue::from(i as i64),
|
key: RawValue::from(i as i64),
|
||||||
|
|
@ -121,15 +114,14 @@ impl VDSet {
|
||||||
};
|
};
|
||||||
proofs_map.insert(*vd, p);
|
proofs_map.insert(*vd, p);
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Self {
|
||||||
root,
|
root,
|
||||||
proofs_map,
|
proofs_map,
|
||||||
tree_depth,
|
|
||||||
vds_hashes,
|
vds_hashes,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
/// builds the verifier_datas tree, and returns the root and the proofs
|
/// builds the verifier_datas tree, and returns the root and the proofs
|
||||||
pub fn new(tree_depth: usize, vds: &[VerifierOnlyCircuitData]) -> Result<Self> {
|
pub fn new(vds: &[VerifierOnlyCircuitData]) -> Self {
|
||||||
// compute the verifier_data's hashes
|
// compute the verifier_data's hashes
|
||||||
let vds_hashes: Vec<HashOut> = vds
|
let vds_hashes: Vec<HashOut> = vds
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -141,7 +133,7 @@ impl VDSet {
|
||||||
.map(|h| Hash(h.elements))
|
.map(|h| Hash(h.elements))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Self::new_from_vds_hashes(tree_depth, vds_hashes)
|
Self::new_from_vds_hashes(vds_hashes)
|
||||||
}
|
}
|
||||||
pub fn root(&self) -> Hash {
|
pub fn root(&self) -> Hash {
|
||||||
self.root
|
self.root
|
||||||
|
|
@ -172,10 +164,9 @@ impl<'de> Deserialize<'de> for VDSet {
|
||||||
{
|
{
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Aux {
|
struct Aux {
|
||||||
tree_depth: usize,
|
|
||||||
vds_hashes: Vec<Hash>,
|
vds_hashes: Vec<Hash>,
|
||||||
}
|
}
|
||||||
let aux = Aux::deserialize(deserializer)?;
|
let aux = Aux::deserialize(deserializer)?;
|
||||||
VDSet::new_from_vds_hashes(aux.tree_depth, aux.vds_hashes).map_err(serde::de::Error::custom)
|
Ok(VDSet::new_from_vds_hashes(aux.vds_hashes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2329,8 +2329,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_eq() -> Result<()> {
|
fn test_operation_verify_eq() -> Result<()> {
|
||||||
let dict1 = dict!(32, {"hello" => 55})?;
|
let dict1 = dict!({"hello" => 55});
|
||||||
let dict2 = dict!(32, {"world" => 55})?;
|
let dict2 = dict!({"world" => 55});
|
||||||
let st1: mainpod::Statement = Statement::contains(dict1.clone(), "hello", 55).into();
|
let st1: mainpod::Statement = Statement::contains(dict1.clone(), "hello", 55).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(dict2.clone(), "world", 55).into();
|
let st2: mainpod::Statement = Statement::contains(dict2.clone(), "world", 55).into();
|
||||||
let st: mainpod::Statement = Statement::equal(
|
let st: mainpod::Statement = Statement::equal(
|
||||||
|
|
@ -2349,8 +2349,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_neq() -> Result<()> {
|
fn test_operation_verify_neq() -> Result<()> {
|
||||||
let dict1 = dict!(32, {"hello" => 55})?;
|
let dict1 = dict!({"hello" => 55});
|
||||||
let dict2 = dict!(32, {"world" => 75})?;
|
let dict2 = dict!({"world" => 75});
|
||||||
let st1: mainpod::Statement = Statement::contains(dict1.clone(), "hello", 55).into();
|
let st1: mainpod::Statement = Statement::contains(dict1.clone(), "hello", 55).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(dict2.clone(), "world", 75).into();
|
let st2: mainpod::Statement = Statement::contains(dict2.clone(), "world", 75).into();
|
||||||
let st: mainpod::Statement = Statement::not_equal(
|
let st: mainpod::Statement = Statement::not_equal(
|
||||||
|
|
@ -2369,8 +2369,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_lt() -> Result<()> {
|
fn test_operation_verify_lt() -> Result<()> {
|
||||||
let dict1 = dict!(32, {"hello" => 55})?;
|
let dict1 = dict!({"hello" => 55});
|
||||||
let dict2 = dict!(32, {"hello" => 56})?;
|
let dict2 = dict!({"hello" => 56});
|
||||||
let st1: mainpod::Statement = Statement::contains(dict1.clone(), "hello", 55).into();
|
let st1: mainpod::Statement = Statement::contains(dict1.clone(), "hello", 55).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(dict2.clone(), "hello", 56).into();
|
let st2: mainpod::Statement = Statement::contains(dict2.clone(), "hello", 56).into();
|
||||||
let st: mainpod::Statement = Statement::lt(
|
let st: mainpod::Statement = Statement::lt(
|
||||||
|
|
@ -2387,8 +2387,8 @@ mod tests {
|
||||||
operation_verify(st, op, prev_statements, Aux::default())?;
|
operation_verify(st, op, prev_statements, Aux::default())?;
|
||||||
|
|
||||||
// Also check negative < negative
|
// Also check negative < negative
|
||||||
let dict3 = dict!(32, {"hola" => -56})?;
|
let dict3 = dict!({"hola" => -56});
|
||||||
let dict4 = dict!(32, {"mundo" => -55})?;
|
let dict4 = dict!({"mundo" => -55});
|
||||||
let st3: mainpod::Statement = Statement::contains(dict3.clone(), "hola", -56).into();
|
let st3: mainpod::Statement = Statement::contains(dict3.clone(), "hola", -56).into();
|
||||||
let st4: mainpod::Statement = Statement::contains(dict4.clone(), "mundo", -55).into();
|
let st4: mainpod::Statement = Statement::contains(dict4.clone(), "mundo", -55).into();
|
||||||
let st: mainpod::Statement = Statement::lt(
|
let st: mainpod::Statement = Statement::lt(
|
||||||
|
|
@ -2421,12 +2421,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_lteq() -> Result<()> {
|
fn test_operation_verify_lteq() -> Result<()> {
|
||||||
let local = dict!(32, {
|
let local = dict!({
|
||||||
"n55" => 55,
|
"n55" => 55,
|
||||||
"n56" => 56,
|
"n56" => 56,
|
||||||
"n_56" => -56,
|
"n_56" => -56,
|
||||||
"n_55" => -55,
|
"n_55" => -55,
|
||||||
})?;
|
});
|
||||||
let st1: mainpod::Statement = Statement::contains(local.clone(), "n55", 55).into();
|
let st1: mainpod::Statement = Statement::contains(local.clone(), "n55", 55).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(local.clone(), "n56", 56).into();
|
let st2: mainpod::Statement = Statement::contains(local.clone(), "n56", 56).into();
|
||||||
let st: mainpod::Statement = Statement::lt_eq(
|
let st: mainpod::Statement = Statement::lt_eq(
|
||||||
|
|
@ -2511,11 +2511,11 @@ mod tests {
|
||||||
let v1 = hash_values(&input_values);
|
let v1 = hash_values(&input_values);
|
||||||
let [v2, v3] = input_values;
|
let [v2, v3] = input_values;
|
||||||
|
|
||||||
let local = dict!(32, {
|
let local = dict!({
|
||||||
"hola" => v1,
|
"hola" => v1,
|
||||||
"mundo" => v2.clone(),
|
"mundo" => v2.clone(),
|
||||||
"!" => v3.clone(),
|
"!" => v3.clone(),
|
||||||
})?;
|
});
|
||||||
|
|
||||||
let st1: mainpod::Statement = Statement::contains(local.clone(), "hola", v1).into();
|
let st1: mainpod::Statement = Statement::contains(local.clone(), "hola", v1).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(local.clone(), "mundo", v2).into();
|
let st2: mainpod::Statement = Statement::contains(local.clone(), "mundo", v2).into();
|
||||||
|
|
@ -2549,11 +2549,11 @@ mod tests {
|
||||||
overflow.not().then_some((a, b, sum))
|
overflow.not().then_some((a, b, sum))
|
||||||
})
|
})
|
||||||
.try_for_each(|(a, b, sum)| {
|
.try_for_each(|(a, b, sum)| {
|
||||||
let local = dict!(32, {
|
let local = dict!({
|
||||||
"sum" => sum,
|
"sum" => sum,
|
||||||
"a" => a,
|
"a" => a,
|
||||||
"b" => b,
|
"b" => b,
|
||||||
})?;
|
});
|
||||||
|
|
||||||
let st1: mainpod::Statement = Statement::contains(local.clone(), "sum", sum).into();
|
let st1: mainpod::Statement = Statement::contains(local.clone(), "sum", sum).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(local.clone(), "a", a).into();
|
let st2: mainpod::Statement = Statement::contains(local.clone(), "a", a).into();
|
||||||
|
|
@ -2588,11 +2588,11 @@ mod tests {
|
||||||
overflow.not().then_some((a, b, prod))
|
overflow.not().then_some((a, b, prod))
|
||||||
})
|
})
|
||||||
.try_for_each(|(a, b, prod)| {
|
.try_for_each(|(a, b, prod)| {
|
||||||
let local = dict!(32, {
|
let local = dict!({
|
||||||
"prod" => prod,
|
"prod" => prod,
|
||||||
"a" => a,
|
"a" => a,
|
||||||
"b" => b,
|
"b" => b,
|
||||||
})?;
|
});
|
||||||
|
|
||||||
let st1: mainpod::Statement =
|
let st1: mainpod::Statement =
|
||||||
Statement::contains(local.clone(), "prod", prod).into();
|
Statement::contains(local.clone(), "prod", prod).into();
|
||||||
|
|
@ -2623,11 +2623,11 @@ mod tests {
|
||||||
fn test_operation_verify_maxof() -> Result<()> {
|
fn test_operation_verify_maxof() -> Result<()> {
|
||||||
I64_TEST_PAIRS.into_iter().try_for_each(|(a, b)| {
|
I64_TEST_PAIRS.into_iter().try_for_each(|(a, b)| {
|
||||||
let max = i64::max(a, b);
|
let max = i64::max(a, b);
|
||||||
let local = dict!(32, {
|
let local = dict!({
|
||||||
"max" => max,
|
"max" => max,
|
||||||
"a" => a,
|
"a" => a,
|
||||||
"b" => b,
|
"b" => b,
|
||||||
})?;
|
});
|
||||||
|
|
||||||
let st1: mainpod::Statement = Statement::contains(local.clone(), "max", max).into();
|
let st1: mainpod::Statement = Statement::contains(local.clone(), "max", max).into();
|
||||||
let st2: mainpod::Statement = Statement::contains(local.clone(), "a", a).into();
|
let st2: mainpod::Statement = Statement::contains(local.clone(), "a", a).into();
|
||||||
|
|
@ -2689,10 +2689,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_lt_to_neq() -> Result<()> {
|
fn test_operation_verify_lt_to_neq() -> Result<()> {
|
||||||
let local = dict!(32,{
|
let local = dict!({
|
||||||
"a" => 10,
|
"a" => 10,
|
||||||
"b" => 20,
|
"b" => 20,
|
||||||
})?;
|
});
|
||||||
let st: mainpod::Statement = Statement::not_equal(
|
let st: mainpod::Statement = Statement::not_equal(
|
||||||
AnchoredKey::from((&local, "a")),
|
AnchoredKey::from((&local, "a")),
|
||||||
AnchoredKey::from((&local, "b")),
|
AnchoredKey::from((&local, "b")),
|
||||||
|
|
@ -2714,11 +2714,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_transitive_eq() -> Result<()> {
|
fn test_operation_verify_transitive_eq() -> Result<()> {
|
||||||
let local = dict!(32,{
|
let local = dict!({
|
||||||
"a" => 10,
|
"a" => 10,
|
||||||
"b" => 10,
|
"b" => 10,
|
||||||
"c" => 10,
|
"c" => 10,
|
||||||
})?;
|
});
|
||||||
let st: mainpod::Statement = Statement::equal(
|
let st: mainpod::Statement = Statement::equal(
|
||||||
AnchoredKey::from((&local, "a")),
|
AnchoredKey::from((&local, "a")),
|
||||||
AnchoredKey::from((&local, "c")),
|
AnchoredKey::from((&local, "c")),
|
||||||
|
|
@ -2745,8 +2745,6 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_sintains() -> Result<()> {
|
fn test_operation_verify_sintains() -> Result<()> {
|
||||||
let params = Params::default();
|
|
||||||
|
|
||||||
let kvs = [
|
let kvs = [
|
||||||
(1.into(), 55.into()),
|
(1.into(), 55.into()),
|
||||||
(2.into(), 88.into()),
|
(2.into(), 88.into()),
|
||||||
|
|
@ -2754,14 +2752,14 @@ mod tests {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
let mt = MerkleTree::new(params.max_depth_mt_containers, &kvs)?;
|
let mt = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let root = mt.root();
|
let root = mt.root();
|
||||||
let key = Value::from(5);
|
let key = Value::from(5);
|
||||||
let local = dict!(32,{
|
let local = dict!({
|
||||||
"merkle_root" => root,
|
"merkle_root" => root,
|
||||||
"key" => key.clone(),
|
"key" => key.clone(),
|
||||||
})?;
|
});
|
||||||
let root_ak = AnchoredKey::from((&local, "merkle_root"));
|
let root_ak = AnchoredKey::from((&local, "merkle_root"));
|
||||||
let key_ak = AnchoredKey::from((&local, "key"));
|
let key_ak = AnchoredKey::from((&local, "key"));
|
||||||
|
|
||||||
|
|
@ -2785,8 +2783,6 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_contains() -> Result<()> {
|
fn test_operation_verify_contains() -> Result<()> {
|
||||||
let params = Params::default();
|
|
||||||
|
|
||||||
let kvs = [
|
let kvs = [
|
||||||
(1.into(), 55.into()),
|
(1.into(), 55.into()),
|
||||||
(2.into(), 88.into()),
|
(2.into(), 88.into()),
|
||||||
|
|
@ -2794,16 +2790,16 @@ mod tests {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
let mt = MerkleTree::new(params.max_depth_mt_containers, &kvs)?;
|
let mt = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let root = mt.root();
|
let root = mt.root();
|
||||||
let key = Value::from(175);
|
let key = Value::from(175);
|
||||||
let (value, key_pf) = mt.prove(&key.raw())?;
|
let (value, key_pf) = mt.prove(&key.raw())?;
|
||||||
let local = dict!(32,{
|
let local = dict!({
|
||||||
"merkle_root" => root,
|
"merkle_root" => root,
|
||||||
"key" => key.clone(),
|
"key" => key.clone(),
|
||||||
"value" => value,
|
"value" => value,
|
||||||
})?;
|
});
|
||||||
let root_ak = AnchoredKey::from((&local, "merkle_root"));
|
let root_ak = AnchoredKey::from((&local, "merkle_root"));
|
||||||
let key_ak = AnchoredKey::from((&local, "key"));
|
let key_ak = AnchoredKey::from((&local, "key"));
|
||||||
let value_ak = AnchoredKey::from((&local, "value"));
|
let value_ak = AnchoredKey::from((&local, "value"));
|
||||||
|
|
@ -2833,9 +2829,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_merkle_insert() -> Result<()> {
|
fn test_operation_verify_merkle_insert() -> Result<()> {
|
||||||
let params = Params::default();
|
let mut tree = MerkleTree::new(&[].into());
|
||||||
|
|
||||||
let mut tree = MerkleTree::new(params.max_depth_mt_containers, &[].into())?;
|
|
||||||
|
|
||||||
let key = Value::from(175);
|
let key = Value::from(175);
|
||||||
let value = Value::from(0);
|
let value = Value::from(0);
|
||||||
|
|
@ -2862,12 +2856,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_merkle_update() -> Result<()> {
|
fn test_operation_verify_merkle_update() -> Result<()> {
|
||||||
let params = Params::default();
|
let mut tree = MerkleTree::new(&[(175.into(), 55.into())].into());
|
||||||
|
|
||||||
let mut tree = MerkleTree::new(
|
|
||||||
params.max_depth_mt_containers,
|
|
||||||
&[(175.into(), 55.into())].into(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let key = Value::from(175);
|
let key = Value::from(175);
|
||||||
let value = Value::from(0);
|
let value = Value::from(0);
|
||||||
|
|
@ -2894,12 +2883,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_operation_verify_merkle_delete() -> Result<()> {
|
fn test_operation_verify_merkle_delete() -> Result<()> {
|
||||||
let params = Params::default();
|
let mut tree = MerkleTree::new(&[(175.into(), 55.into())].into());
|
||||||
|
|
||||||
let mut tree = MerkleTree::new(
|
|
||||||
params.max_depth_mt_containers,
|
|
||||||
&[(175.into(), 55.into())].into(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let key = Value::from(175);
|
let key = Value::from(175);
|
||||||
let state_transition_proof = tree.delete(&key.raw())?;
|
let state_transition_proof = tree.delete(&key.raw())?;
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ pub mod tests {
|
||||||
fn test_empty_pod() {
|
fn test_empty_pod() {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
|
|
||||||
let empty_pod = EmptyPod::new_boxed(¶ms, VDSet::new(8, &[]).unwrap());
|
let empty_pod = EmptyPod::new_boxed(¶ms, VDSet::new(&[]));
|
||||||
empty_pod.verify().unwrap();
|
empty_pod.verify().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -851,7 +851,7 @@ pub mod tests {
|
||||||
println!("{:#?}", params);
|
println!("{:#?}", params);
|
||||||
let mut vds = DEFAULT_VD_LIST.clone();
|
let mut vds = DEFAULT_VD_LIST.clone();
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(&vds);
|
||||||
|
|
||||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
||||||
let signer = Signer(SecretKey(BigUint::one()));
|
let signer = Signer(SecretKey(BigUint::one()));
|
||||||
|
|
@ -875,7 +875,7 @@ pub mod tests {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
println!("{:#?}", params);
|
println!("{:#?}", params);
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &[]).unwrap();
|
let vd_set = VDSet::new(&[]);
|
||||||
|
|
||||||
// Calculate rec common first to avoid duplicate metrics in `pod_builder.prove`
|
// Calculate rec common first to avoid duplicate metrics in `pod_builder.prove`
|
||||||
let _rec_common_circuit_data = cache_get_standard_rec_main_pod_common_circuit_data();
|
let _rec_common_circuit_data = cache_get_standard_rec_main_pod_common_circuit_data();
|
||||||
|
|
@ -912,7 +912,7 @@ pub mod tests {
|
||||||
};
|
};
|
||||||
let mut vds = DEFAULT_VD_LIST.clone();
|
let mut vds = DEFAULT_VD_LIST.clone();
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(&vds);
|
||||||
|
|
||||||
let mut gov_id_builder = frontend::SignedDictBuilder::new(¶ms);
|
let mut gov_id_builder = frontend::SignedDictBuilder::new(¶ms);
|
||||||
gov_id_builder.insert("idNumber", "4242424242");
|
gov_id_builder.insert("idNumber", "4242424242");
|
||||||
|
|
@ -970,7 +970,7 @@ pub mod tests {
|
||||||
};
|
};
|
||||||
let mut vds = DEFAULT_VD_LIST.clone();
|
let mut vds = DEFAULT_VD_LIST.clone();
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(&vds);
|
||||||
|
|
||||||
let builder = frontend::MainPodBuilder::new(¶ms, &vd_set);
|
let builder = frontend::MainPodBuilder::new(¶ms, &vd_set);
|
||||||
println!("{}", builder);
|
println!("{}", builder);
|
||||||
|
|
@ -1014,7 +1014,7 @@ pub mod tests {
|
||||||
};
|
};
|
||||||
let mut vds = DEFAULT_VD_LIST.clone();
|
let mut vds = DEFAULT_VD_LIST.clone();
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(&vds);
|
||||||
|
|
||||||
let pod_builder = frontend::MainPodBuilder::new(¶ms, &vd_set);
|
let pod_builder = frontend::MainPodBuilder::new(¶ms, &vd_set);
|
||||||
|
|
||||||
|
|
@ -1080,7 +1080,7 @@ pub mod tests {
|
||||||
println!("{:#?}", params);
|
println!("{:#?}", params);
|
||||||
let mut vds = DEFAULT_VD_LIST.clone();
|
let mut vds = DEFAULT_VD_LIST.clone();
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(&vds);
|
||||||
|
|
||||||
let mut cpb_builder = CustomPredicateBatchBuilder::new(params.clone(), "cpb".into());
|
let mut cpb_builder = CustomPredicateBatchBuilder::new(params.clone(), "cpb".into());
|
||||||
let stb0 = STB::new(NP::Contains)
|
let stb0 = STB::new(NP::Contains)
|
||||||
|
|
@ -1104,8 +1104,8 @@ pub mod tests {
|
||||||
|
|
||||||
let mut pod_builder = MainPodBuilder::new(¶ms, &vd_set);
|
let mut pod_builder = MainPodBuilder::new(¶ms, &vd_set);
|
||||||
|
|
||||||
let dict = dict!(32, {"score" => 42})?;
|
let dict = dict!({"score" => 42});
|
||||||
let secret_dict = dict!(32, {"key" => 42})?;
|
let secret_dict = dict!({"key" => 42});
|
||||||
let st0 = pod_builder.priv_op(frontend::Operation::dict_contains(
|
let st0 = pod_builder.priv_op(frontend::Operation::dict_contains(
|
||||||
dict.clone(),
|
dict.clone(),
|
||||||
"score",
|
"score",
|
||||||
|
|
@ -1136,7 +1136,7 @@ pub mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let mut builder = MainPodBuilder::new(¶ms, &DEFAULT_VD_SET);
|
let mut builder = MainPodBuilder::new(¶ms, &DEFAULT_VD_SET);
|
||||||
let set: HashSet<_> = [1, 2, 3].into_iter().map(|n| n.into()).collect();
|
let set: HashSet<_> = [1, 2, 3].into_iter().map(|n| n.into()).collect();
|
||||||
let set = Set::new(params.max_depth_mt_containers, set).unwrap();
|
let set = Set::new(set);
|
||||||
builder.pub_op(frontend::Operation::set_contains(set, 1))?;
|
builder.pub_op(frontend::Operation::set_contains(set, 1))?;
|
||||||
|
|
||||||
let prover = Prover {};
|
let prover = Prover {};
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ pub mod tests {
|
||||||
fn test_mock_empty_pod() {
|
fn test_mock_empty_pod() {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
|
|
||||||
let empty_pod = MockEmptyPod::new_boxed(¶ms, VDSet::new(8, &[]).unwrap());
|
let empty_pod = MockEmptyPod::new_boxed(¶ms, VDSet::new(&[]));
|
||||||
empty_pod.verify().unwrap();
|
empty_pod.verify().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ use crate::{
|
||||||
backends::plonky2::{
|
backends::plonky2::{
|
||||||
basetypes::D,
|
basetypes::D,
|
||||||
circuits::common::{CircuitBuilderPod, ValueTarget},
|
circuits::common::{CircuitBuilderPod, ValueTarget},
|
||||||
error::Result,
|
error::{Error, Result},
|
||||||
primitives::merkletree::{
|
primitives::merkletree::{
|
||||||
MerkleClaimAndProof, MerkleTreeOp, MerkleTreeStateTransitionProof,
|
MerkleClaimAndProof, MerkleTreeOp, MerkleTreeStateTransitionProof, TreeError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
measure_gates_begin, measure_gates_end,
|
measure_gates_begin, measure_gates_end,
|
||||||
|
|
@ -159,6 +159,13 @@ impl MerkleClaimAndProofTarget {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
mp: &MerkleClaimAndProof,
|
mp: &MerkleClaimAndProof,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if mp.proof.siblings.len() > self.max_depth {
|
||||||
|
return Err(Error::Tree(TreeError::circuit_depth_too_small(
|
||||||
|
self.max_depth,
|
||||||
|
mp.proof.siblings.len(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
pw.set_bool_target(self.enabled, enabled)?;
|
pw.set_bool_target(self.enabled, enabled)?;
|
||||||
pw.set_hash_target(self.root, HashOut::from_vec(mp.root.0.to_vec()))?;
|
pw.set_hash_target(self.root, HashOut::from_vec(mp.root.0.to_vec()))?;
|
||||||
pw.set_target_arr(&self.key.elements, &mp.key.0)?;
|
pw.set_target_arr(&self.key.elements, &mp.key.0)?;
|
||||||
|
|
@ -166,7 +173,6 @@ impl MerkleClaimAndProofTarget {
|
||||||
pw.set_bool_target(self.existence, mp.proof.existence)?;
|
pw.set_bool_target(self.existence, mp.proof.existence)?;
|
||||||
|
|
||||||
// pad siblings with zeros to length max_depth
|
// pad siblings with zeros to length max_depth
|
||||||
assert!(mp.proof.siblings.len() <= self.max_depth);
|
|
||||||
for (i, sibling) in mp
|
for (i, sibling) in mp
|
||||||
.proof
|
.proof
|
||||||
.siblings
|
.siblings
|
||||||
|
|
@ -265,6 +271,12 @@ impl MerkleProofExistenceTarget {
|
||||||
mp: &MerkleClaimAndProof,
|
mp: &MerkleClaimAndProof,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
assert!(mp.proof.existence); // sanity check
|
assert!(mp.proof.existence); // sanity check
|
||||||
|
if mp.proof.siblings.len() > self.max_depth {
|
||||||
|
return Err(Error::Tree(TreeError::circuit_depth_too_small(
|
||||||
|
self.max_depth,
|
||||||
|
mp.proof.siblings.len(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
pw.set_bool_target(self.enabled, enabled)?;
|
pw.set_bool_target(self.enabled, enabled)?;
|
||||||
pw.set_hash_target(self.root, HashOut::from_vec(mp.root.0.to_vec()))?;
|
pw.set_hash_target(self.root, HashOut::from_vec(mp.root.0.to_vec()))?;
|
||||||
|
|
@ -272,7 +284,6 @@ impl MerkleProofExistenceTarget {
|
||||||
pw.set_target_arr(&self.value.elements, &mp.value.0)?;
|
pw.set_target_arr(&self.value.elements, &mp.value.0)?;
|
||||||
|
|
||||||
// pad siblings with zeros to length max_depth
|
// pad siblings with zeros to length max_depth
|
||||||
assert!(mp.proof.siblings.len() <= self.max_depth);
|
|
||||||
for (i, sibling) in mp
|
for (i, sibling) in mp
|
||||||
.proof
|
.proof
|
||||||
.siblings
|
.siblings
|
||||||
|
|
@ -610,6 +621,14 @@ impl MerkleTreeStateTransitionProofTarget {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
mp: &MerkleTreeStateTransitionProof,
|
mp: &MerkleTreeStateTransitionProof,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let new_siblings = mp.siblings.clone();
|
||||||
|
if new_siblings.len() > self.max_depth {
|
||||||
|
return Err(Error::Tree(TreeError::circuit_depth_too_small(
|
||||||
|
self.max_depth,
|
||||||
|
new_siblings.len(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
pw.set_bool_target(self.enabled, enabled)?;
|
pw.set_bool_target(self.enabled, enabled)?;
|
||||||
pw.set_target(self.op, F::from_canonical_u8(mp.op as u8))?;
|
pw.set_target(self.op, F::from_canonical_u8(mp.op as u8))?;
|
||||||
|
|
||||||
|
|
@ -633,9 +652,6 @@ impl MerkleTreeStateTransitionProofTarget {
|
||||||
pw.set_target_arr(&self.op_key.elements, &mp.op_key.0)?;
|
pw.set_target_arr(&self.op_key.elements, &mp.op_key.0)?;
|
||||||
pw.set_target_arr(&self.op_value.elements, &mp.op_value.0)?;
|
pw.set_target_arr(&self.op_value.elements, &mp.op_value.0)?;
|
||||||
|
|
||||||
let new_siblings = mp.siblings.clone();
|
|
||||||
|
|
||||||
assert!(new_siblings.len() <= self.max_depth);
|
|
||||||
for (i, sibling) in new_siblings
|
for (i, sibling) in new_siblings
|
||||||
.iter()
|
.iter()
|
||||||
.chain(iter::repeat(&EMPTY_HASH))
|
.chain(iter::repeat(&EMPTY_HASH))
|
||||||
|
|
@ -683,7 +699,7 @@ pub mod tests {
|
||||||
let mut pw = PartialWitness::<F>::new();
|
let mut pw = PartialWitness::<F>::new();
|
||||||
|
|
||||||
let key = RawValue::from(hash_value(&RawValue::from(i)));
|
let key = RawValue::from(hash_value(&RawValue::from(i)));
|
||||||
let expected_path = keypath(max_depth, key)?;
|
let expected_path = keypath(key);
|
||||||
|
|
||||||
// small circuit logic to check
|
// small circuit logic to check
|
||||||
// expected_path_targ==keypath_target(key_targ)
|
// expected_path_targ==keypath_target(key_targ)
|
||||||
|
|
@ -769,7 +785,7 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
let tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let (key, value, proof) = if existence {
|
let (key, value, proof) = if existence {
|
||||||
let key = RawValue::from(hash_value(&RawValue::from(5)));
|
let key = RawValue::from(hash_value(&RawValue::from(5)));
|
||||||
|
|
@ -783,9 +799,9 @@ pub mod tests {
|
||||||
assert_eq!(proof.existence, existence);
|
assert_eq!(proof.existence, existence);
|
||||||
|
|
||||||
if existence {
|
if existence {
|
||||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
MerkleTree::verify(tree.root(), &proof, &key, &value)?;
|
||||||
} else {
|
} else {
|
||||||
MerkleTree::verify_nonexistence(max_depth, tree.root(), &proof, &key)?;
|
MerkleTree::verify_nonexistence(tree.root(), &proof, &key)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// circuit
|
// circuit
|
||||||
|
|
@ -826,14 +842,14 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
let tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let key = RawValue::from(hash_value(&RawValue::from(5)));
|
let key = RawValue::from(hash_value(&RawValue::from(5)));
|
||||||
let (value, proof) = tree.prove(&key)?;
|
let (value, proof) = tree.prove(&key)?;
|
||||||
assert_eq!(value, RawValue::from(5));
|
assert_eq!(value, RawValue::from(5));
|
||||||
assert!(proof.existence);
|
assert!(proof.existence);
|
||||||
|
|
||||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
MerkleTree::verify(tree.root(), &proof, &key, &value)?;
|
||||||
|
|
||||||
// circuit
|
// circuit
|
||||||
let config = CircuitConfig::standard_recursion_config();
|
let config = CircuitConfig::standard_recursion_config();
|
||||||
|
|
@ -877,7 +893,7 @@ pub mod tests {
|
||||||
kvs.insert(RawValue::from(13), RawValue::from(1013));
|
kvs.insert(RawValue::from(13), RawValue::from(1013));
|
||||||
|
|
||||||
let max_depth = 5;
|
let max_depth = 5;
|
||||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
let tree = MerkleTree::new(&kvs);
|
||||||
// existence
|
// existence
|
||||||
test_merkletree_edgecase_opt(max_depth, &tree, RawValue::from(5))?;
|
test_merkletree_edgecase_opt(max_depth, &tree, RawValue::from(5))?;
|
||||||
// non-existence case i) expected leaf does not exist
|
// non-existence case i) expected leaf does not exist
|
||||||
|
|
@ -906,9 +922,9 @@ pub mod tests {
|
||||||
|
|
||||||
// verify the proof (non circuit)
|
// verify the proof (non circuit)
|
||||||
if proof.existence {
|
if proof.existence {
|
||||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
MerkleTree::verify(tree.root(), &proof, &key, &value)?;
|
||||||
} else {
|
} else {
|
||||||
MerkleTree::verify_nonexistence(max_depth, tree.root(), &proof, &key)?;
|
MerkleTree::verify_nonexistence(tree.root(), &proof, &key)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// circuit
|
// circuit
|
||||||
|
|
@ -939,7 +955,7 @@ pub mod tests {
|
||||||
kvs.insert(RawValue::from(i), RawValue::from(i));
|
kvs.insert(RawValue::from(i), RawValue::from(i));
|
||||||
}
|
}
|
||||||
let max_depth = 16;
|
let max_depth = 16;
|
||||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
let tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let key = RawValue::from(3);
|
let key = RawValue::from(3);
|
||||||
let (value, proof) = tree.prove(&key)?;
|
let (value, proof) = tree.prove(&key)?;
|
||||||
|
|
@ -947,11 +963,11 @@ pub mod tests {
|
||||||
// build another tree with an extra key-value, so that it has a
|
// build another tree with an extra key-value, so that it has a
|
||||||
// different root
|
// different root
|
||||||
kvs.insert(RawValue::from(100), RawValue::from(100));
|
kvs.insert(RawValue::from(100), RawValue::from(100));
|
||||||
let tree2 = MerkleTree::new(max_depth, &kvs)?;
|
let tree2 = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
MerkleTree::verify(tree.root(), &proof, &key, &value)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MerkleTree::verify(max_depth, tree2.root(), &proof, &key, &value)
|
MerkleTree::verify(tree2.root(), &proof, &key, &value)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.inner()
|
.inner()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -1002,10 +1018,10 @@ pub mod tests {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// sanity check, run the out-circuit proof verification
|
// sanity check, run the out-circuit proof verification
|
||||||
if expect_pass {
|
if expect_pass {
|
||||||
MerkleTree::verify_state_transition(max_depth, state_transition_proof)?;
|
MerkleTree::verify_state_transition(state_transition_proof)?;
|
||||||
} else {
|
} else {
|
||||||
// expect out-circuit verification to fail
|
// expect out-circuit verification to fail
|
||||||
let _ = MerkleTree::verify_state_transition(max_depth, state_transition_proof).is_err();
|
let _ = MerkleTree::verify_state_transition(state_transition_proof).is_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = CircuitConfig::standard_recursion_config();
|
let config = CircuitConfig::standard_recursion_config();
|
||||||
|
|
@ -1034,7 +1050,7 @@ pub mod tests {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
||||||
}
|
}
|
||||||
let mut tree = MerkleTree::new(max_depth, &kvs)?;
|
let mut tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
// key=37 shares path with key=5, till the level 6, needing 2 extra
|
// key=37 shares path with key=5, till the level 6, needing 2 extra
|
||||||
// 'empty' nodes between the original position of key=5 with the new
|
// 'empty' nodes between the original position of key=5 with the new
|
||||||
|
|
@ -1093,7 +1109,7 @@ pub mod tests {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
||||||
}
|
}
|
||||||
let mut tree = MerkleTree::new(max_depth, &kvs)?;
|
let mut tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let old_root = tree.root();
|
let old_root = tree.root();
|
||||||
let key = RawValue::from(4294967295); // 0xffffffff
|
let key = RawValue::from(4294967295); // 0xffffffff
|
||||||
|
|
@ -1157,7 +1173,7 @@ pub mod tests {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
||||||
}
|
}
|
||||||
let mut tree = MerkleTree::new(max_depth, &kvs)?;
|
let mut tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
// key=37 shares path with key=5, till the level 6, needing 2 extra
|
// key=37 shares path with key=5, till the level 6, needing 2 extra
|
||||||
// 'empty' nodes between the original position of key=5 with the new
|
// 'empty' nodes between the original position of key=5 with the new
|
||||||
|
|
@ -1200,7 +1216,6 @@ pub mod tests {
|
||||||
other_leaf: None,
|
other_leaf: None,
|
||||||
};
|
};
|
||||||
let altered_root = altered_proof.compute_root_from_leaf(
|
let altered_root = altered_proof.compute_root_from_leaf(
|
||||||
max_depth,
|
|
||||||
&state_transition_proof.op_key,
|
&state_transition_proof.op_key,
|
||||||
Some(state_transition_proof.op_value),
|
Some(state_transition_proof.op_value),
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -1220,7 +1235,7 @@ pub mod tests {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
||||||
}
|
}
|
||||||
let mut tree = MerkleTree::new(max_depth, &kvs)?;
|
let mut tree = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
let key = RawValue::from(37);
|
let key = RawValue::from(37);
|
||||||
let value = RawValue::from(1037);
|
let value = RawValue::from(1037);
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ pub enum TreeInnerError {
|
||||||
InvalidStateTransitionProogArg(String),
|
InvalidStateTransitionProogArg(String),
|
||||||
#[error("state transition proof does not verify, reason: {0}")]
|
#[error("state transition proof does not verify, reason: {0}")]
|
||||||
StateTransitionProofFail(String),
|
StateTransitionProofFail(String),
|
||||||
#[error("key too short (key length: {0}) for the max_depth: {1}")]
|
#[error("circuit max_depth {0} is smaller than proof depth {1}")]
|
||||||
TooShortKey(usize, usize),
|
CircuitDepthTooSmall(usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(thiserror::Error)]
|
#[derive(thiserror::Error)]
|
||||||
|
|
@ -78,7 +78,7 @@ impl TreeError {
|
||||||
pub(crate) fn state_transition_fail(reason: String) -> Self {
|
pub(crate) fn state_transition_fail(reason: String) -> Self {
|
||||||
new!(StateTransitionProofFail(reason))
|
new!(StateTransitionProofFail(reason))
|
||||||
}
|
}
|
||||||
pub(crate) fn too_short_key(depth: usize, max_depth: usize) -> Self {
|
pub(crate) fn circuit_depth_too_small(circuit_depth: usize, proof_depth: usize) -> Self {
|
||||||
new!(TooShortKey(depth, max_depth))
|
new!(CircuitDepthTooSmall(circuit_depth, proof_depth))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,28 +13,30 @@ pub use circuit::*;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub use error::{TreeError, TreeResult};
|
pub use error::{TreeError, TreeResult};
|
||||||
|
|
||||||
|
/// Theoretical max depth of a merkle tree. This limits appears because we store keys of 256 bits.
|
||||||
|
const MAX_DEPTH: usize = 256;
|
||||||
|
|
||||||
/// Implements the MerkleTree specified at
|
/// Implements the MerkleTree specified at
|
||||||
/// <https://0xparc.github.io/pod2/merkletree.html>
|
/// <https://0xparc.github.io/pod2/merkletree.html>
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MerkleTree {
|
pub struct MerkleTree {
|
||||||
max_depth: usize,
|
|
||||||
root: Node,
|
root: Node,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MerkleTree {
|
impl MerkleTree {
|
||||||
/// builds a new `MerkleTree` where the leaves contain the given key-values
|
/// builds a new `MerkleTree` where the leaves contain the given key-values
|
||||||
pub fn new(max_depth: usize, kvs: &HashMap<RawValue, RawValue>) -> TreeResult<Self> {
|
pub fn new(kvs: &HashMap<RawValue, RawValue>) -> Self {
|
||||||
// Start with an empty node as root.
|
// Start with an empty node as root.
|
||||||
let mut root = Node::None;
|
let mut root = Node::None;
|
||||||
|
|
||||||
// Iterate over key-value pairs (if any) and add them.
|
// Iterate over key-value pairs (if any) and add them.
|
||||||
for (k, v) in kvs.iter() {
|
for (k, v) in kvs.iter() {
|
||||||
root.apply_op(max_depth, MerkleTreeOp::Insert, *k, Some(*v))?;
|
root.apply_op(MerkleTreeOp::Insert, *k, Some(*v)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in hashes.
|
// Fill in hashes.
|
||||||
let _ = root.compute_hash();
|
let _ = root.compute_hash();
|
||||||
Ok(Self { max_depth, root })
|
Self { root }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the root of the tree
|
/// returns the root of the tree
|
||||||
|
|
@ -42,15 +44,10 @@ impl MerkleTree {
|
||||||
self.root.hash()
|
self.root.hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the max_depth parameter from the tree
|
|
||||||
pub fn max_depth(&self) -> usize {
|
|
||||||
self.max_depth
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the value at the given key
|
/// returns the value at the given key
|
||||||
pub fn get(&self, key: &RawValue) -> TreeResult<RawValue> {
|
pub fn get(&self, key: &RawValue) -> TreeResult<RawValue> {
|
||||||
let path = keypath(self.max_depth, *key)?;
|
let path = keypath(*key);
|
||||||
let (key_resolution, _) = self.root.down(0, self.max_depth, path, None)?;
|
let (key_resolution, _) = self.root.down(0, path, None);
|
||||||
match key_resolution {
|
match key_resolution {
|
||||||
Some((k, v)) if &k == key => Ok(v),
|
Some((k, v)) if &k == key => Ok(v),
|
||||||
_ => Err(TreeError::key_not_found()),
|
_ => Err(TreeError::key_not_found()),
|
||||||
|
|
@ -59,15 +56,9 @@ impl MerkleTree {
|
||||||
|
|
||||||
/// returns a boolean indicating whether the key exists in the tree
|
/// returns a boolean indicating whether the key exists in the tree
|
||||||
pub fn contains(&self, key: &RawValue) -> TreeResult<bool> {
|
pub fn contains(&self, key: &RawValue) -> TreeResult<bool> {
|
||||||
let path = keypath(self.max_depth, *key)?;
|
let path = keypath(*key);
|
||||||
match self.root.down(0, self.max_depth, path, None) {
|
match self.root.down(0, path, None) {
|
||||||
Ok((Some((k, _)), _)) => {
|
(Some((k, _)), _) if &k == key => Ok(true),
|
||||||
if &k == key {
|
|
||||||
Ok(true)
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Ok(false),
|
_ => Ok(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +72,7 @@ impl MerkleTree {
|
||||||
|
|
||||||
let old_root: Hash = self.root.hash();
|
let old_root: Hash = self.root.hash();
|
||||||
self.root
|
self.root
|
||||||
.apply_op(self.max_depth, MerkleTreeOp::Insert, *key, Some(*value))?;
|
.apply_op(MerkleTreeOp::Insert, *key, Some(*value))?;
|
||||||
let new_root = self.root.compute_hash();
|
let new_root = self.root.compute_hash();
|
||||||
|
|
||||||
let (v, proof) = self.prove(key)?;
|
let (v, proof) = self.prove(key)?;
|
||||||
|
|
@ -110,7 +101,7 @@ impl MerkleTree {
|
||||||
|
|
||||||
let old_root: Hash = self.root.hash();
|
let old_root: Hash = self.root.hash();
|
||||||
self.root
|
self.root
|
||||||
.apply_op(self.max_depth, MerkleTreeOp::Update, *key, Some(*value))?;
|
.apply_op(MerkleTreeOp::Update, *key, Some(*value))?;
|
||||||
let new_root = self.root.compute_hash();
|
let new_root = self.root.compute_hash();
|
||||||
|
|
||||||
let (v, proof) = self.prove(key)?;
|
let (v, proof) = self.prove(key)?;
|
||||||
|
|
@ -134,8 +125,7 @@ impl MerkleTree {
|
||||||
let (value, proof_existence) = self.prove(key)?;
|
let (value, proof_existence) = self.prove(key)?;
|
||||||
|
|
||||||
let old_root: Hash = self.root.hash();
|
let old_root: Hash = self.root.hash();
|
||||||
self.root
|
self.root.apply_op(MerkleTreeOp::Delete, *key, None)?;
|
||||||
.apply_op(self.max_depth, MerkleTreeOp::Delete, *key, None)?;
|
|
||||||
let new_root = self.root.compute_hash();
|
let new_root = self.root.compute_hash();
|
||||||
|
|
||||||
let proof = self.prove_nonexistence(key)?;
|
let proof = self.prove_nonexistence(key)?;
|
||||||
|
|
@ -157,14 +147,11 @@ impl MerkleTree {
|
||||||
/// the tree. It returns the `value` of the leaf at the given `key`, and the
|
/// the tree. It returns the `value` of the leaf at the given `key`, and the
|
||||||
/// `MerkleProof`.
|
/// `MerkleProof`.
|
||||||
pub fn prove(&self, key: &RawValue) -> TreeResult<(RawValue, MerkleProof)> {
|
pub fn prove(&self, key: &RawValue) -> TreeResult<(RawValue, MerkleProof)> {
|
||||||
let path = keypath(self.max_depth, *key)?;
|
let path = keypath(*key);
|
||||||
|
|
||||||
let mut siblings: Vec<Hash> = Vec::new();
|
let mut siblings: Vec<Hash> = Vec::new();
|
||||||
|
|
||||||
match self
|
match self.root.down(0, path, Some(&mut siblings)) {
|
||||||
.root
|
|
||||||
.down(0, self.max_depth, path, Some(&mut siblings))?
|
|
||||||
{
|
|
||||||
(Some((k, v)), _) if &k == key => Ok((
|
(Some((k, v)), _) if &k == key => Ok((
|
||||||
v,
|
v,
|
||||||
MerkleProof {
|
MerkleProof {
|
||||||
|
|
@ -182,15 +169,12 @@ impl MerkleTree {
|
||||||
/// the key-value pair in the leaf reached as a result of
|
/// the key-value pair in the leaf reached as a result of
|
||||||
/// resolving `key` as well as a `MerkleProof`.
|
/// resolving `key` as well as a `MerkleProof`.
|
||||||
pub fn prove_nonexistence(&self, key: &RawValue) -> TreeResult<MerkleProof> {
|
pub fn prove_nonexistence(&self, key: &RawValue) -> TreeResult<MerkleProof> {
|
||||||
let path = keypath(self.max_depth, *key)?;
|
let path = keypath(*key);
|
||||||
|
|
||||||
let mut siblings: Vec<Hash> = Vec::new();
|
let mut siblings: Vec<Hash> = Vec::new();
|
||||||
|
|
||||||
// note: non-existence of a key can be in 2 cases:
|
// note: non-existence of a key can be in 2 cases:
|
||||||
match self
|
match self.root.down(0, path, Some(&mut siblings)) {
|
||||||
.root
|
|
||||||
.down(0, self.max_depth, path, Some(&mut siblings))?
|
|
||||||
{
|
|
||||||
// case i) the expected leaf does not exist
|
// case i) the expected leaf does not exist
|
||||||
(None, _) => Ok(MerkleProof {
|
(None, _) => Ok(MerkleProof {
|
||||||
existence: false,
|
existence: false,
|
||||||
|
|
@ -203,20 +187,19 @@ impl MerkleTree {
|
||||||
siblings,
|
siblings,
|
||||||
other_leaf: Some((k, v)),
|
other_leaf: Some((k, v)),
|
||||||
}),
|
}),
|
||||||
_ => Err(TreeError::key_not_found()),
|
_ => Err(TreeError::key_exists()),
|
||||||
}
|
}
|
||||||
// both cases prove that the given key don't exist in the tree.
|
// both cases prove that the given key don't exist in the tree.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// verifies an inclusion proof for the given `key` and `value`
|
/// verifies an inclusion proof for the given `key` and `value`
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
max_depth: usize,
|
|
||||||
root: Hash,
|
root: Hash,
|
||||||
proof: &MerkleProof,
|
proof: &MerkleProof,
|
||||||
key: &RawValue,
|
key: &RawValue,
|
||||||
value: &RawValue,
|
value: &RawValue,
|
||||||
) -> TreeResult<()> {
|
) -> TreeResult<()> {
|
||||||
let h = proof.compute_root_from_leaf(max_depth, key, Some(*value))?;
|
let h = proof.compute_root_from_leaf(key, Some(*value))?;
|
||||||
|
|
||||||
if h != root {
|
if h != root {
|
||||||
Err(TreeError::proof_fail("inclusion".to_string()))
|
Err(TreeError::proof_fail("inclusion".to_string()))
|
||||||
|
|
@ -227,12 +210,7 @@ impl MerkleTree {
|
||||||
|
|
||||||
/// verifies a non-inclusion proof for the given `key`, that is, the given
|
/// verifies a non-inclusion proof for the given `key`, that is, the given
|
||||||
/// `key` does not exist in the tree
|
/// `key` does not exist in the tree
|
||||||
pub fn verify_nonexistence(
|
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, key: &RawValue) -> TreeResult<()> {
|
||||||
max_depth: usize,
|
|
||||||
root: Hash,
|
|
||||||
proof: &MerkleProof,
|
|
||||||
key: &RawValue,
|
|
||||||
) -> TreeResult<()> {
|
|
||||||
match proof.other_leaf {
|
match proof.other_leaf {
|
||||||
Some((k, _v)) if &k == key => {
|
Some((k, _v)) if &k == key => {
|
||||||
Err(TreeError::invalid_proof("non-existence".to_string()))
|
Err(TreeError::invalid_proof("non-existence".to_string()))
|
||||||
|
|
@ -240,7 +218,7 @@ impl MerkleTree {
|
||||||
_ => {
|
_ => {
|
||||||
let k = proof.other_leaf.map(|(k, _)| k).unwrap_or(*key);
|
let k = proof.other_leaf.map(|(k, _)| k).unwrap_or(*key);
|
||||||
let v: Option<RawValue> = proof.other_leaf.map(|(_, v)| v);
|
let v: Option<RawValue> = proof.other_leaf.map(|(_, v)| v);
|
||||||
let h = proof.compute_root_from_leaf(max_depth, &k, v)?;
|
let h = proof.compute_root_from_leaf(&k, v)?;
|
||||||
|
|
||||||
if h != root {
|
if h != root {
|
||||||
Err(TreeError::proof_fail("exclusion".to_string()))
|
Err(TreeError::proof_fail("exclusion".to_string()))
|
||||||
|
|
@ -251,10 +229,7 @@ impl MerkleTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_state_transition(
|
pub fn verify_state_transition(proof: &MerkleTreeStateTransitionProof) -> TreeResult<()> {
|
||||||
max_depth: usize,
|
|
||||||
proof: &MerkleTreeStateTransitionProof,
|
|
||||||
) -> TreeResult<()> {
|
|
||||||
let mut old_siblings = proof.op_proof.siblings.clone();
|
let mut old_siblings = proof.op_proof.siblings.clone();
|
||||||
let new_siblings = proof.siblings.clone();
|
let new_siblings = proof.siblings.clone();
|
||||||
|
|
||||||
|
|
@ -267,12 +242,11 @@ impl MerkleTree {
|
||||||
old_root: proof.new_root,
|
old_root: proof.new_root,
|
||||||
..proof.clone()
|
..proof.clone()
|
||||||
};
|
};
|
||||||
Self::verify_state_transition(max_depth, &equivalent_insertion_proof)
|
Self::verify_state_transition(&equivalent_insertion_proof)
|
||||||
}
|
}
|
||||||
MerkleTreeOp::Update => {
|
MerkleTreeOp::Update => {
|
||||||
// check that for the old_root, (op_key, value) *does* exist in the tree
|
// check that for the old_root, (op_key, value) *does* exist in the tree
|
||||||
Self::verify(
|
Self::verify(
|
||||||
max_depth,
|
|
||||||
proof.old_root,
|
proof.old_root,
|
||||||
&proof.op_proof,
|
&proof.op_proof,
|
||||||
&proof.op_key,
|
&proof.op_key,
|
||||||
|
|
@ -280,7 +254,6 @@ impl MerkleTree {
|
||||||
)?;
|
)?;
|
||||||
// check that for the new_root, (op_key, op_value) *does* exist in the tree
|
// check that for the new_root, (op_key, op_value) *does* exist in the tree
|
||||||
Self::verify(
|
Self::verify(
|
||||||
max_depth,
|
|
||||||
proof.new_root,
|
proof.new_root,
|
||||||
&MerkleProof {
|
&MerkleProof {
|
||||||
existence: true,
|
existence: true,
|
||||||
|
|
@ -301,16 +274,10 @@ impl MerkleTree {
|
||||||
}
|
}
|
||||||
MerkleTreeOp::Insert => {
|
MerkleTreeOp::Insert => {
|
||||||
// check that for the old_root, the new_key does not exist in the tree
|
// check that for the old_root, the new_key does not exist in the tree
|
||||||
Self::verify_nonexistence(
|
Self::verify_nonexistence(proof.old_root, &proof.op_proof, &proof.op_key)?;
|
||||||
max_depth,
|
|
||||||
proof.old_root,
|
|
||||||
&proof.op_proof,
|
|
||||||
&proof.op_key,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// check that new_siblings verify with the new_root
|
// check that new_siblings verify with the new_root
|
||||||
Self::verify(
|
Self::verify(
|
||||||
max_depth,
|
|
||||||
proof.new_root,
|
proof.new_root,
|
||||||
&MerkleProof {
|
&MerkleProof {
|
||||||
existence: true,
|
existence: true,
|
||||||
|
|
@ -323,8 +290,8 @@ impl MerkleTree {
|
||||||
|
|
||||||
// if other_leaf exists, check path divergence
|
// if other_leaf exists, check path divergence
|
||||||
if let Some((other_key, _)) = proof.op_proof.other_leaf {
|
if let Some((other_key, _)) = proof.op_proof.other_leaf {
|
||||||
let old_path = keypath(max_depth, other_key)?;
|
let old_path = keypath(other_key);
|
||||||
let new_path = keypath(max_depth, proof.op_key)?;
|
let new_path = keypath(proof.op_key);
|
||||||
|
|
||||||
let divergence_lvl: usize =
|
let divergence_lvl: usize =
|
||||||
match zip_eq(old_path, new_path).position(|(x, y)| x != y) {
|
match zip_eq(old_path, new_path).position(|(x, y)| x != y) {
|
||||||
|
|
@ -455,26 +422,12 @@ impl MerkleProof {
|
||||||
/// Computes the root of the Merkle tree suggested by a Merkle proof given a
|
/// Computes the root of the Merkle tree suggested by a Merkle proof given a
|
||||||
/// key & value. If a value is not provided, the terminal node is assumed to
|
/// key & value. If a value is not provided, the terminal node is assumed to
|
||||||
/// be empty.
|
/// be empty.
|
||||||
fn compute_root_from_leaf(
|
fn compute_root_from_leaf(&self, key: &RawValue, value: Option<RawValue>) -> TreeResult<Hash> {
|
||||||
&self,
|
let path = keypath(*key);
|
||||||
max_depth: usize,
|
|
||||||
key: &RawValue,
|
|
||||||
value: Option<RawValue>,
|
|
||||||
) -> TreeResult<Hash> {
|
|
||||||
let path = keypath(max_depth, *key)?;
|
|
||||||
let h = kv_hash(key, value);
|
let h = kv_hash(key, value);
|
||||||
self.compute_root_from_node(max_depth, &h, path)
|
self.compute_root_from_node(&h, path)
|
||||||
}
|
}
|
||||||
fn compute_root_from_node(
|
fn compute_root_from_node(&self, node_hash: &Hash, path: Vec<bool>) -> TreeResult<Hash> {
|
||||||
&self,
|
|
||||||
max_depth: usize,
|
|
||||||
node_hash: &Hash,
|
|
||||||
path: Vec<bool>,
|
|
||||||
) -> TreeResult<Hash> {
|
|
||||||
if self.siblings.len() >= max_depth {
|
|
||||||
return Err(TreeError::max_depth());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut h = *node_hash;
|
let mut h = *node_hash;
|
||||||
for (i, sibling) in self.siblings.iter().enumerate().rev() {
|
for (i, sibling) in self.siblings.iter().enumerate().rev() {
|
||||||
let mut input: Vec<F> = if path[i] {
|
let mut input: Vec<F> = if path[i] {
|
||||||
|
|
@ -677,26 +630,21 @@ impl Node {
|
||||||
fn down(
|
fn down(
|
||||||
&self,
|
&self,
|
||||||
lvl: usize,
|
lvl: usize,
|
||||||
max_depth: usize,
|
|
||||||
path: Vec<bool>,
|
path: Vec<bool>,
|
||||||
mut siblings: Option<&mut Vec<Hash>>,
|
mut siblings: Option<&mut Vec<Hash>>,
|
||||||
) -> TreeResult<(Option<(RawValue, RawValue)>, usize)> {
|
) -> (Option<(RawValue, RawValue)>, usize) {
|
||||||
if lvl >= max_depth {
|
|
||||||
return Err(TreeError::max_depth());
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::Intermediate(n) => {
|
Self::Intermediate(n) => {
|
||||||
if path[lvl] {
|
if path[lvl] {
|
||||||
if let Some(s) = siblings.as_mut() {
|
if let Some(s) = siblings.as_mut() {
|
||||||
s.push(n.left.hash());
|
s.push(n.left.hash());
|
||||||
}
|
}
|
||||||
n.right.down(lvl + 1, max_depth, path, siblings)
|
n.right.down(lvl + 1, path, siblings)
|
||||||
} else {
|
} else {
|
||||||
if let Some(s) = siblings.as_mut() {
|
if let Some(s) = siblings.as_mut() {
|
||||||
s.push(n.right.hash());
|
s.push(n.right.hash());
|
||||||
}
|
}
|
||||||
n.left.down(lvl + 1, max_depth, path, siblings)
|
n.left.down(lvl + 1, path, siblings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Leaf(Leaf {
|
Self::Leaf(Leaf {
|
||||||
|
|
@ -704,20 +652,19 @@ impl Node {
|
||||||
value,
|
value,
|
||||||
path: _p,
|
path: _p,
|
||||||
hash: _h,
|
hash: _h,
|
||||||
}) => Ok((Some((*key, *value)), lvl)),
|
}) => (Some((*key, *value)), lvl),
|
||||||
_ => Ok((None, lvl)),
|
_ => (None, lvl),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies given Merkle tree op without computing hashes.
|
/// Applies given Merkle tree op without computing hashes.
|
||||||
pub(crate) fn apply_op(
|
pub(crate) fn apply_op(
|
||||||
&mut self,
|
&mut self,
|
||||||
max_depth: usize,
|
|
||||||
op: MerkleTreeOp,
|
op: MerkleTreeOp,
|
||||||
key: RawValue,
|
key: RawValue,
|
||||||
maybe_value: Option<RawValue>,
|
maybe_value: Option<RawValue>,
|
||||||
) -> TreeResult<()> {
|
) -> TreeResult<()> {
|
||||||
let key_path = keypath(max_depth, key)?;
|
let key_path = keypath(key);
|
||||||
// Rule out invalid arguments
|
// Rule out invalid arguments
|
||||||
match (op, maybe_value) {
|
match (op, maybe_value) {
|
||||||
(MerkleTreeOp::Insert, None) | (MerkleTreeOp::Update, None) => {
|
(MerkleTreeOp::Insert, None) | (MerkleTreeOp::Update, None) => {
|
||||||
|
|
@ -736,7 +683,7 @@ impl Node {
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
// Loop through to leaf.
|
// Loop through to leaf.
|
||||||
self.apply_op_loop(0, max_depth, op, key, &key_path, maybe_value)?;
|
self.apply_op_loop(0, op, key, &key_path, maybe_value)?;
|
||||||
|
|
||||||
// If we are dealing with a deletion, normalise along key
|
// If we are dealing with a deletion, normalise along key
|
||||||
// path.
|
// path.
|
||||||
|
|
@ -777,28 +724,23 @@ impl Node {
|
||||||
fn apply_op_loop(
|
fn apply_op_loop(
|
||||||
&mut self,
|
&mut self,
|
||||||
lvl: usize,
|
lvl: usize,
|
||||||
max_depth: usize,
|
|
||||||
op: MerkleTreeOp,
|
op: MerkleTreeOp,
|
||||||
key: RawValue,
|
key: RawValue,
|
||||||
key_path: &[bool],
|
key_path: &[bool],
|
||||||
maybe_value: Option<RawValue>,
|
maybe_value: Option<RawValue>,
|
||||||
) -> TreeResult<()> {
|
) -> TreeResult<()> {
|
||||||
if lvl >= max_depth {
|
|
||||||
return Err(TreeError::max_depth());
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::Intermediate(n) => {
|
Self::Intermediate(n) => {
|
||||||
if key_path[lvl] {
|
if key_path[lvl] {
|
||||||
n.right
|
n.right
|
||||||
.apply_op_loop(lvl + 1, max_depth, op, key, key_path, maybe_value)
|
.apply_op_loop(lvl + 1, op, key, key_path, maybe_value)
|
||||||
} else {
|
} else {
|
||||||
n.left
|
n.left
|
||||||
.apply_op_loop(lvl + 1, max_depth, op, key, key_path, maybe_value)
|
.apply_op_loop(lvl + 1, op, key, key_path, maybe_value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
*self = Self::op_node_check(max_depth, lvl, self, op, key, key_path, maybe_value)?;
|
*self = Self::op_node_check(lvl, self, op, key, key_path, maybe_value)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -813,7 +755,6 @@ impl Node {
|
||||||
/// value is replaced in the case of an update and the leaf removed
|
/// value is replaced in the case of an update and the leaf removed
|
||||||
/// in the case of a deletion.
|
/// in the case of a deletion.
|
||||||
pub(crate) fn op_node_check(
|
pub(crate) fn op_node_check(
|
||||||
max_depth: usize,
|
|
||||||
lvl: usize,
|
lvl: usize,
|
||||||
node: &Node,
|
node: &Node,
|
||||||
op: MerkleTreeOp,
|
op: MerkleTreeOp,
|
||||||
|
|
@ -826,7 +767,7 @@ impl Node {
|
||||||
// Invalid args are assumed to have been ruled out.
|
// Invalid args are assumed to have been ruled out.
|
||||||
match (op, node, maybe_value) {
|
match (op, node, maybe_value) {
|
||||||
// Insertion case
|
// Insertion case
|
||||||
(Insert, Node::None, Some(value)) => Ok(Node::Leaf(Leaf::new(max_depth, key, value)?)),
|
(Insert, Node::None, Some(value)) => Ok(Node::Leaf(Leaf::new(key, value))),
|
||||||
(Insert, Node::Leaf(l), Some(value)) => {
|
(Insert, Node::Leaf(l), Some(value)) => {
|
||||||
// in this case, it means that we found a leaf in the new-leaf
|
// in this case, it means that we found a leaf in the new-leaf
|
||||||
// path, thus we need to push both leaves (old-leaf and
|
// path, thus we need to push both leaves (old-leaf and
|
||||||
|
|
@ -845,7 +786,6 @@ impl Node {
|
||||||
let mut new_node = Node::Intermediate(Intermediate::empty());
|
let mut new_node = Node::Intermediate(Intermediate::empty());
|
||||||
new_node.down_till_divergence(
|
new_node.down_till_divergence(
|
||||||
lvl,
|
lvl,
|
||||||
max_depth,
|
|
||||||
old_leaf,
|
old_leaf,
|
||||||
Leaf {
|
Leaf {
|
||||||
hash: None,
|
hash: None,
|
||||||
|
|
@ -859,7 +799,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
// Update case
|
// Update case
|
||||||
(Update, Node::Leaf(l), Some(value)) if l.key == key => {
|
(Update, Node::Leaf(l), Some(value)) if l.key == key => {
|
||||||
Ok(Node::Leaf(Leaf::new(max_depth, key, value)?))
|
Ok(Node::Leaf(Leaf::new(key, value)))
|
||||||
}
|
}
|
||||||
// Deletion case
|
// Deletion case
|
||||||
(Delete, Node::Leaf(l), None) if l.key == key => Ok(Node::None),
|
(Delete, Node::Leaf(l), None) if l.key == key => Ok(Node::None),
|
||||||
|
|
@ -878,14 +818,9 @@ impl Node {
|
||||||
fn down_till_divergence(
|
fn down_till_divergence(
|
||||||
&mut self,
|
&mut self,
|
||||||
lvl: usize,
|
lvl: usize,
|
||||||
max_depth: usize,
|
|
||||||
old_leaf: Leaf,
|
old_leaf: Leaf,
|
||||||
new_leaf: Leaf,
|
new_leaf: Leaf,
|
||||||
) -> TreeResult<()> {
|
) -> TreeResult<()> {
|
||||||
if lvl >= max_depth {
|
|
||||||
return Err(TreeError::max_depth());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Node::Intermediate(ref mut n) = self {
|
if let Node::Intermediate(ref mut n) = self {
|
||||||
if old_leaf.path[lvl] != new_leaf.path[lvl] {
|
if old_leaf.path[lvl] != new_leaf.path[lvl] {
|
||||||
// reached divergence in next level, set the leaves as children
|
// reached divergence in next level, set the leaves as children
|
||||||
|
|
@ -903,14 +838,10 @@ impl Node {
|
||||||
// no divergence yet, continue going down
|
// no divergence yet, continue going down
|
||||||
if new_leaf.path[lvl] {
|
if new_leaf.path[lvl] {
|
||||||
n.right = Box::new(Node::Intermediate(Intermediate::empty()));
|
n.right = Box::new(Node::Intermediate(Intermediate::empty()));
|
||||||
return n
|
return n.right.down_till_divergence(lvl + 1, old_leaf, new_leaf);
|
||||||
.right
|
|
||||||
.down_till_divergence(lvl + 1, max_depth, old_leaf, new_leaf);
|
|
||||||
} else {
|
} else {
|
||||||
n.left = Box::new(Node::Intermediate(Intermediate::empty()));
|
n.left = Box::new(Node::Intermediate(Intermediate::empty()));
|
||||||
return n
|
return n.left.down_till_divergence(lvl + 1, old_leaf, new_leaf);
|
||||||
.left
|
|
||||||
.down_till_divergence(lvl + 1, max_depth, old_leaf, new_leaf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -956,13 +887,13 @@ pub(crate) struct Leaf {
|
||||||
pub(crate) value: RawValue,
|
pub(crate) value: RawValue,
|
||||||
}
|
}
|
||||||
impl Leaf {
|
impl Leaf {
|
||||||
fn new(max_depth: usize, key: RawValue, value: RawValue) -> TreeResult<Self> {
|
fn new(key: RawValue, value: RawValue) -> Self {
|
||||||
Ok(Self {
|
Self {
|
||||||
hash: None,
|
hash: None,
|
||||||
path: keypath(max_depth, key)?,
|
path: keypath(key),
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
fn compute_hash(&mut self) -> Hash {
|
fn compute_hash(&mut self) -> Hash {
|
||||||
let h = kv_hash(&self.key, Some(self.value));
|
let h = kv_hash(&self.key, Some(self.value));
|
||||||
|
|
@ -981,17 +912,12 @@ impl Leaf {
|
||||||
// max-depth? ie, what happens when two keys share the same path for more bits
|
// max-depth? ie, what happens when two keys share the same path for more bits
|
||||||
// than the max_depth?
|
// than the max_depth?
|
||||||
/// returns the path of the given key
|
/// returns the path of the given key
|
||||||
pub(crate) fn keypath(max_depth: usize, k: RawValue) -> TreeResult<Vec<bool>> {
|
pub(crate) fn keypath(k: RawValue) -> Vec<bool> {
|
||||||
let bytes = k.to_bytes();
|
let bytes = k.to_bytes();
|
||||||
if max_depth > 8 * bytes.len() {
|
debug_assert_eq!(MAX_DEPTH, bytes.len() * 8);
|
||||||
// note that our current keys are of Value type, which are 4 Goldilocks
|
(0..MAX_DEPTH)
|
||||||
// field elements, ie ~256 bits, therefore the max_depth can not be
|
|
||||||
// bigger than 256.
|
|
||||||
return Err(TreeError::too_short_key(8 * bytes.len(), max_depth));
|
|
||||||
}
|
|
||||||
Ok((0..max_depth)
|
|
||||||
.map(|n| bytes[n / 8] & (1 << (n % 8)) != 0)
|
.map(|n| bytes[n / 8] & (1 << (n % 8)) != 0)
|
||||||
.collect())
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Iter<'a> {
|
pub struct Iter<'a> {
|
||||||
|
|
@ -1035,7 +961,6 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merkletree() -> TreeResult<()> {
|
fn test_merkletree() -> TreeResult<()> {
|
||||||
let max_depth: usize = 32;
|
|
||||||
let mut kvs = HashMap::new();
|
let mut kvs = HashMap::new();
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
|
|
@ -1047,7 +972,7 @@ pub mod tests {
|
||||||
let value = RawValue::from(1013);
|
let value = RawValue::from(1013);
|
||||||
kvs.insert(key, value);
|
kvs.insert(key, value);
|
||||||
|
|
||||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
let tree = MerkleTree::new(&kvs);
|
||||||
// when printing the tree, it should print the same tree as in
|
// when printing the tree, it should print the same tree as in
|
||||||
// https://0xparc.github.io/pod2/merkletree.html#example-2
|
// https://0xparc.github.io/pod2/merkletree.html#example-2
|
||||||
println!("{}", tree);
|
println!("{}", tree);
|
||||||
|
|
@ -1057,7 +982,7 @@ pub mod tests {
|
||||||
assert_eq!(v, RawValue::from(1013));
|
assert_eq!(v, RawValue::from(1013));
|
||||||
println!("{}", proof);
|
println!("{}", proof);
|
||||||
|
|
||||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
MerkleTree::verify(tree.root(), &proof, &key, &value)?;
|
||||||
|
|
||||||
// Exclusion checks
|
// Exclusion checks
|
||||||
let key = RawValue::from(12);
|
let key = RawValue::from(12);
|
||||||
|
|
@ -1068,42 +993,40 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
println!("{}", proof);
|
println!("{}", proof);
|
||||||
|
|
||||||
MerkleTree::verify_nonexistence(max_depth, tree.root(), &proof, &key)?;
|
MerkleTree::verify_nonexistence(tree.root(), &proof, &key)?;
|
||||||
|
|
||||||
let key = RawValue::from(1);
|
let key = RawValue::from(1);
|
||||||
let proof = tree.prove_nonexistence(&RawValue::from(1))?;
|
let proof = tree.prove_nonexistence(&RawValue::from(1))?;
|
||||||
assert_eq!(proof.other_leaf, None);
|
assert_eq!(proof.other_leaf, None);
|
||||||
println!("{}", proof);
|
println!("{}", proof);
|
||||||
|
|
||||||
MerkleTree::verify_nonexistence(max_depth, tree.root(), &proof, &key)?;
|
MerkleTree::verify_nonexistence(tree.root(), &proof, &key)?;
|
||||||
|
|
||||||
// Check iterator
|
// Check iterator
|
||||||
let collected_kvs: Vec<_> = tree.into_iter().collect::<Vec<_>>();
|
let collected_kvs: Vec<_> = tree.into_iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
// Expected key ordering
|
// Expected key ordering
|
||||||
let cmp = |max_depth: usize| {
|
let cmp = |k1, k2| {
|
||||||
move |k1, k2| {
|
let path1 = keypath(k1);
|
||||||
let path1 = keypath(max_depth, k1).unwrap();
|
let path2 = keypath(k2);
|
||||||
let path2 = keypath(max_depth, k2).unwrap();
|
|
||||||
|
|
||||||
let first_unequal_bits = std::iter::zip(path1, path2).find(|(b1, b2)| b1 != b2);
|
let first_unequal_bits = std::iter::zip(path1, path2).find(|(b1, b2)| b1 != b2);
|
||||||
|
|
||||||
match first_unequal_bits {
|
match first_unequal_bits {
|
||||||
Some((b1, b2)) => {
|
Some((b1, b2)) => {
|
||||||
if !b1 & b2 {
|
if !b1 & b2 {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else {
|
} else {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => Ordering::Equal,
|
|
||||||
}
|
}
|
||||||
|
_ => Ordering::Equal,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sorted_kvs = kvs
|
let sorted_kvs = kvs
|
||||||
.iter()
|
.iter()
|
||||||
.sorted_by(|(k1, _), (k2, _)| cmp(max_depth)(**k1, **k2))
|
.sorted_by(|(k1, _), (k2, _)| cmp(**k1, **k2))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
assert_eq!(collected_kvs, sorted_kvs);
|
assert_eq!(collected_kvs, sorted_kvs);
|
||||||
|
|
@ -1113,13 +1036,12 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_state_transition() -> TreeResult<()> {
|
fn test_state_transition() -> TreeResult<()> {
|
||||||
let max_depth: usize = 32;
|
|
||||||
let mut kvs = HashMap::new();
|
let mut kvs = HashMap::new();
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tree = MerkleTree::new(max_depth, &kvs)?;
|
let mut tree = MerkleTree::new(&kvs);
|
||||||
let old_root = tree.root();
|
let old_root = tree.root();
|
||||||
|
|
||||||
// key=37 shares path with key=5, till the level 6, needing 2 extra
|
// key=37 shares path with key=5, till the level 6, needing 2 extra
|
||||||
|
|
@ -1129,7 +1051,7 @@ pub mod tests {
|
||||||
let value = RawValue::from(1037);
|
let value = RawValue::from(1037);
|
||||||
let state_transition_proof = tree.insert(&key, &value)?;
|
let state_transition_proof = tree.insert(&key, &value)?;
|
||||||
|
|
||||||
MerkleTree::verify_state_transition(max_depth, &state_transition_proof)?;
|
MerkleTree::verify_state_transition(&state_transition_proof)?;
|
||||||
assert_eq!(state_transition_proof.old_root, old_root);
|
assert_eq!(state_transition_proof.old_root, old_root);
|
||||||
assert_eq!(state_transition_proof.new_root, tree.root());
|
assert_eq!(state_transition_proof.new_root, tree.root());
|
||||||
assert_eq!(state_transition_proof.op_key, key);
|
assert_eq!(state_transition_proof.op_key, key);
|
||||||
|
|
@ -1140,7 +1062,7 @@ pub mod tests {
|
||||||
// should be the same (mutatis mutandis).
|
// should be the same (mutatis mutandis).
|
||||||
let mut tree_with_deleted_key = tree.clone();
|
let mut tree_with_deleted_key = tree.clone();
|
||||||
let state_transition_proof1 = tree_with_deleted_key.delete(&key)?;
|
let state_transition_proof1 = tree_with_deleted_key.delete(&key)?;
|
||||||
MerkleTree::verify_state_transition(max_depth, &state_transition_proof1)?;
|
MerkleTree::verify_state_transition(&state_transition_proof1)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state_transition_proof1.old_root,
|
state_transition_proof1.old_root,
|
||||||
state_transition_proof.new_root
|
state_transition_proof.new_root
|
||||||
|
|
@ -1172,14 +1094,14 @@ pub mod tests {
|
||||||
let value = RawValue::from(1021);
|
let value = RawValue::from(1021);
|
||||||
let state_transition_proof = tree_with_another_leaf.insert(&key, &value)?;
|
let state_transition_proof = tree_with_another_leaf.insert(&key, &value)?;
|
||||||
|
|
||||||
MerkleTree::verify_state_transition(max_depth, &state_transition_proof)?;
|
MerkleTree::verify_state_transition(&state_transition_proof)?;
|
||||||
|
|
||||||
// Alternatively add this key with another value then update.
|
// Alternatively add this key with another value then update.
|
||||||
let value1 = RawValue::from(99);
|
let value1 = RawValue::from(99);
|
||||||
tree.insert(&key, &value1)?;
|
tree.insert(&key, &value1)?;
|
||||||
let state_transition_proof1 = tree.update(&key, &value)?;
|
let state_transition_proof1 = tree.update(&key, &value)?;
|
||||||
|
|
||||||
MerkleTree::verify_state_transition(max_depth, &state_transition_proof1)?;
|
MerkleTree::verify_state_transition(&state_transition_proof1)?;
|
||||||
|
|
||||||
// `tree` and `tree_with_another_leaf` should coincide.
|
// `tree` and `tree_with_another_leaf` should coincide.
|
||||||
assert_eq!(tree.root(), tree_with_another_leaf.root());
|
assert_eq!(tree.root(), tree_with_another_leaf.root());
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::{collections::HashSet, sync::LazyLock};
|
||||||
use custom::eth_dos_batch;
|
use custom::eth_dos_batch;
|
||||||
use num::BigUint;
|
use num::BigUint;
|
||||||
|
|
||||||
pub static MOCK_VD_SET: LazyLock<VDSet> = LazyLock::new(|| VDSet::new(6, &[]).unwrap());
|
pub static MOCK_VD_SET: LazyLock<VDSet> = LazyLock::new(|| VDSet::new(&[]));
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backends::plonky2::{primitives::ec::schnorr::SecretKey, signer::Signer},
|
backends::plonky2::{primitives::ec::schnorr::SecretKey, signer::Signer},
|
||||||
|
|
@ -50,8 +50,7 @@ pub fn zu_kyc_pod_builder(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| Value::from(*s))
|
.map(|s| Value::from(*s))
|
||||||
.collect();
|
.collect();
|
||||||
let sanction_set =
|
let sanction_set = Value::from(Set::new(sanctions_values));
|
||||||
Value::from(Set::new(params.max_depth_mt_containers, sanctions_values).unwrap());
|
|
||||||
|
|
||||||
let mut kyc = MainPodBuilder::new(params, vd_set);
|
let mut kyc = MainPodBuilder::new(params, vd_set);
|
||||||
kyc.pub_op(Operation::dict_signed_by(gov_id))?;
|
kyc.pub_op(Operation::dict_signed_by(gov_id))?;
|
||||||
|
|
@ -72,13 +71,11 @@ pub fn zu_kyc_pod_builder(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zu_kyc_pod_request(gov_signer: &Value, pay_signer: &Value) -> Result<PodRequest> {
|
pub fn zu_kyc_pod_request(gov_signer: &Value, pay_signer: &Value) -> Result<PodRequest> {
|
||||||
let params = Params::default();
|
|
||||||
let sanctions_values: HashSet<Value> = ZU_KYC_SANCTION_LIST
|
let sanctions_values: HashSet<Value> = ZU_KYC_SANCTION_LIST
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| Value::from(*s))
|
.map(|s| Value::from(*s))
|
||||||
.collect();
|
.collect();
|
||||||
let sanction_set =
|
let sanction_set = Value::from(Set::new(sanctions_values));
|
||||||
Value::from(Set::new(params.max_depth_mt_containers, sanctions_values).unwrap());
|
|
||||||
let input = format!(
|
let input = format!(
|
||||||
r#"
|
r#"
|
||||||
REQUEST(
|
REQUEST(
|
||||||
|
|
@ -347,9 +344,8 @@ pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
|
||||||
alice_friend_pods.push(friend.sign(&charlie_signer).unwrap());
|
alice_friend_pods.push(friend.sign(&charlie_signer).unwrap());
|
||||||
|
|
||||||
let good_boy_issuers = Value::from(Set::new(
|
let good_boy_issuers = Value::from(Set::new(
|
||||||
params.max_depth_mt_containers,
|
|
||||||
good_boy_issuers.into_iter().map(Value::from).collect(),
|
good_boy_issuers.into_iter().map(Value::from).collect(),
|
||||||
)?);
|
));
|
||||||
|
|
||||||
let builder = great_boy_pod_builder(
|
let builder = great_boy_pod_builder(
|
||||||
¶ms,
|
¶ms,
|
||||||
|
|
@ -433,6 +429,6 @@ pub fn tickets_pod_full_flow(params: &Params, vd_set: &VDSet) -> Result<MainPodB
|
||||||
&signed_dict,
|
&signed_dict,
|
||||||
123,
|
123,
|
||||||
true,
|
true,
|
||||||
&Set::new(params.max_depth_mt_containers, HashSet::new())?,
|
&Set::new(HashSet::new()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ mod tests {
|
||||||
let mut mp_builder = MainPodBuilder::new(¶ms, vd_set);
|
let mut mp_builder = MainPodBuilder::new(¶ms, vd_set);
|
||||||
|
|
||||||
let set_values: HashSet<Value> = [1, 2, 3].iter().map(|i| Value::from(*i)).collect();
|
let set_values: HashSet<Value> = [1, 2, 3].iter().map(|i| Value::from(*i)).collect();
|
||||||
let s1 = Set::new(params.max_depth_mt_containers, set_values)?;
|
let s1 = Set::new(set_values);
|
||||||
let s2 = 1;
|
let s2 = 1;
|
||||||
|
|
||||||
let set_contains = mp_builder.pub_op(Operation::set_contains(s1, s2))?;
|
let set_contains = mp_builder.pub_op(Operation::set_contains(s1, s2))?;
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ impl SignedDictBuilder {
|
||||||
|
|
||||||
pub fn sign<S: Signer>(&self, signer: &S) -> Result<SignedDict> {
|
pub fn sign<S: Signer>(&self, signer: &S) -> Result<SignedDict> {
|
||||||
// Sign committed KV store.
|
// Sign committed KV store.
|
||||||
let dict = Dictionary::new(self.params.max_depth_mt_containers, self.kvs.clone())?;
|
let dict = Dictionary::new(self.kvs.clone());
|
||||||
// NOTE: This is the same way that `TypedValue::Dictionary` computes the `RawValue`
|
// NOTE: This is the same way that `TypedValue::Dictionary` computes the `RawValue`
|
||||||
let msg_raw = RawValue::from(dict.commitment());
|
let msg_raw = RawValue::from(dict.commitment());
|
||||||
let signature = signer.sign(msg_raw);
|
let signature = signer.sign(msg_raw);
|
||||||
|
|
@ -1026,11 +1026,11 @@ pub mod tests {
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
let mut builder = SignedDictBuilder::new(¶ms);
|
let mut builder = SignedDictBuilder::new(¶ms);
|
||||||
|
|
||||||
let dict = dict!(params.max_depth_mt_containers, {
|
let dict = dict!({
|
||||||
"a" => 1,
|
"a" => 1,
|
||||||
"b" => 2,
|
"b" => 2,
|
||||||
"c" => 3,
|
"c" => 3,
|
||||||
})?;
|
});
|
||||||
let dict_root = Value::from(dict.clone());
|
let dict_root = Value::from(dict.clone());
|
||||||
builder.insert("dict", dict_root);
|
builder.insert("dict", dict_root);
|
||||||
|
|
||||||
|
|
@ -1042,7 +1042,7 @@ pub mod tests {
|
||||||
.pub_op(Operation::dict_signed_by(&signed_dict))
|
.pub_op(Operation::dict_signed_by(&signed_dict))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let st0 = signed_dict.get_statement("dict").unwrap();
|
let st0 = signed_dict.get_statement("dict").unwrap();
|
||||||
let local = dict!(32, {"key" => "a"})?;
|
let local = dict!({"key" => "a"});
|
||||||
let st1 = builder
|
let st1 = builder
|
||||||
.op(true, vec![], Operation::dict_contains(local, "key", "a"))
|
.op(true, vec![], Operation::dict_contains(local, "key", "a"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -1115,7 +1115,7 @@ pub mod tests {
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||||
|
|
||||||
let empty_set = Set::new(params.max_depth_mt_containers, [].into())?;
|
let empty_set = Set::new([].into());
|
||||||
|
|
||||||
let mut set1 = empty_set.clone();
|
let mut set1 = empty_set.clone();
|
||||||
set1.insert(&1.into())?;
|
set1.insert(&1.into())?;
|
||||||
|
|
@ -1163,7 +1163,7 @@ pub mod tests {
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||||
|
|
||||||
let array1 = Array::new(params.max_depth_mt_containers, [1.into()].into())?;
|
let array1 = Array::new([1.into()].into());
|
||||||
|
|
||||||
let mut array2 = array1.clone();
|
let mut array2 = array1.clone();
|
||||||
array2.update(0, &5.into())?;
|
array2.update(0, &5.into())?;
|
||||||
|
|
@ -1217,7 +1217,7 @@ pub mod tests {
|
||||||
"owner",
|
"owner",
|
||||||
Value::from(pk),
|
Value::from(pk),
|
||||||
))?;
|
))?;
|
||||||
let local = dict!(32, { "known_secret" => sk.clone() })?;
|
let local = dict!({ "known_secret" => sk.clone() });
|
||||||
let st1 = builder.priv_op(Operation::dict_contains(
|
let st1 = builder.priv_op(Operation::dict_contains(
|
||||||
local,
|
local,
|
||||||
"known_secret",
|
"known_secret",
|
||||||
|
|
@ -1262,7 +1262,7 @@ pub mod tests {
|
||||||
.pub_op(Operation::dict_signed_by(&signed_dict))
|
.pub_op(Operation::dict_signed_by(&signed_dict))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let st0 = signed_dict.get_statement("owner").unwrap();
|
let st0 = signed_dict.get_statement("owner").unwrap();
|
||||||
let local = dict!(32, {"known_secret" => SecretKey(BigUint::from(123u32))})?;
|
let local = dict!({"known_secret" => SecretKey(BigUint::from(123u32))});
|
||||||
let st1 = builder
|
let st1 = builder
|
||||||
.op(
|
.op(
|
||||||
true,
|
true,
|
||||||
|
|
@ -1333,7 +1333,7 @@ pub mod tests {
|
||||||
let params = Params::default();
|
let params = Params::default();
|
||||||
let vd_set = &*MOCK_VD_SET;
|
let vd_set = &*MOCK_VD_SET;
|
||||||
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
let mut builder = MainPodBuilder::new(¶ms, vd_set);
|
||||||
let local = dict!(32, {"a" => 3, "b" => 27}).unwrap();
|
let local = dict!({"a" => 3, "b" => 27});
|
||||||
let value_of_a = Statement::contains(local.clone(), "a", 3);
|
let value_of_a = Statement::contains(local.clone(), "a", 3);
|
||||||
let value_of_b = Statement::contains(local.clone(), "b", 27);
|
let value_of_b = Statement::contains(local.clone(), "b", 27);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,19 +89,18 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_value_serialization() {
|
fn test_value_serialization() {
|
||||||
let params = &Params::default();
|
|
||||||
// Pairs of values and their expected serialized representations
|
// Pairs of values and their expected serialized representations
|
||||||
let values = vec![
|
let values = vec![
|
||||||
(TypedValue::String("hello".to_string()), "\"hello\""),
|
(TypedValue::String("hello".to_string()), "\"hello\""),
|
||||||
(TypedValue::Int(42), "{\"Int\":\"42\"}"),
|
(TypedValue::Int(42), "{\"Int\":\"42\"}"),
|
||||||
(TypedValue::Bool(true), "true"),
|
(TypedValue::Bool(true), "true"),
|
||||||
(
|
(
|
||||||
TypedValue::Array(Array::new(params.max_depth_mt_containers, vec!["foo".into(), false.into()]).unwrap()),
|
TypedValue::Array(Array::new(vec!["foo".into(), false.into()])),
|
||||||
"{\"max_depth\":32,\"array\":[\"foo\",false]}",
|
"{\"array\":[\"foo\",false]}",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
TypedValue::Dictionary(
|
TypedValue::Dictionary(
|
||||||
Dictionary::new(params.max_depth_mt_containers, HashMap::from([
|
Dictionary::new(HashMap::from([
|
||||||
// The set of valid keys is equal to the set of valid JSON keys
|
// The set of valid keys is equal to the set of valid JSON keys
|
||||||
("foo".into(), 123.into()),
|
("foo".into(), 123.into()),
|
||||||
// Empty strings are valid JSON keys
|
// Empty strings are valid JSON keys
|
||||||
|
|
@ -115,13 +114,12 @@ mod tests {
|
||||||
// Keys can contain emojis
|
// Keys can contain emojis
|
||||||
(("🥳".into()), "party time!".into()),
|
(("🥳".into()), "party time!".into()),
|
||||||
]))
|
]))
|
||||||
.unwrap(),
|
|
||||||
),
|
),
|
||||||
"{\"max_depth\":32,\"kvs\":{\"\":\"baz\",\"\\u0000\":\"\",\" hi\":false,\"!@£$%^&&*()\":\"\",\"foo\":{\"Int\":\"123\"},\"🥳\":\"party time!\"}}",
|
"{\"kvs\":{\"\":\"baz\",\"\\u0000\":\"\",\" hi\":false,\"!@£$%^&&*()\":\"\",\"foo\":{\"Int\":\"123\"},\"🥳\":\"party time!\"}}",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
TypedValue::Set(Set::new(params.max_depth_mt_containers, HashSet::from(["foo".into(), "bar".into()])).unwrap()),
|
TypedValue::Set(Set::new(HashSet::from(["foo".into(), "bar".into()]))),
|
||||||
"{\"max_depth\":32,\"set\":[\"bar\",\"foo\"]}",
|
"{\"set\":[\"bar\",\"foo\"]}",
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -147,39 +145,21 @@ mod tests {
|
||||||
builder.insert("very_large_int", 1152921504606846976);
|
builder.insert("very_large_int", 1152921504606846976);
|
||||||
builder.insert(
|
builder.insert(
|
||||||
"a_dict_containing_one_key",
|
"a_dict_containing_one_key",
|
||||||
Dictionary::new(
|
Dictionary::new(HashMap::from([
|
||||||
params.max_depth_mt_containers,
|
("foo".into(), 123.into()),
|
||||||
HashMap::from([
|
(
|
||||||
("foo".into(), 123.into()),
|
"an_array_containing_three_ints".into(),
|
||||||
(
|
Array::new(vec![1.into(), 2.into(), 3.into()]).into(),
|
||||||
"an_array_containing_three_ints".into(),
|
),
|
||||||
Array::new(
|
(
|
||||||
params.max_depth_mt_containers,
|
"a_set_containing_two_strings".into(),
|
||||||
vec![1.into(), 2.into(), 3.into()],
|
Set::new(HashSet::from([
|
||||||
)
|
Array::new(vec!["foo".into(), "bar".into()]).into(),
|
||||||
.unwrap()
|
"baz".into(),
|
||||||
.into(),
|
]))
|
||||||
),
|
.into(),
|
||||||
(
|
),
|
||||||
"a_set_containing_two_strings".into(),
|
])),
|
||||||
Set::new(
|
|
||||||
params.max_depth_mt_containers,
|
|
||||||
HashSet::from([
|
|
||||||
Array::new(
|
|
||||||
params.max_depth_mt_containers,
|
|
||||||
vec!["foo".into(), "bar".into()],
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
.into(),
|
|
||||||
"baz".into(),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
.into(),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
);
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +208,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut vds = DEFAULT_VD_LIST.clone();
|
let mut vds = DEFAULT_VD_LIST.clone();
|
||||||
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
vds.push(rec_main_pod_circuit_data(¶ms).1.verifier_only.clone());
|
||||||
let vd_set = VDSet::new(params.max_depth_mt_vds, &vds).unwrap();
|
let vd_set = VDSet::new(&vds);
|
||||||
|
|
||||||
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
let (gov_id_builder, pay_stub_builder) = zu_kyc_sign_dict_builders(¶ms);
|
||||||
let signer = Signer(SecretKey(1u32.into()));
|
let signer = Signer(SecretKey(1u32.into()));
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ impl<'a> Lowerer<'a> {
|
||||||
// Convert AST args to BuilderArgs
|
// Convert AST args to BuilderArgs
|
||||||
let mut builder = StatementTmplBuilder::new(predicate);
|
let mut builder = StatementTmplBuilder::new(predicate);
|
||||||
for arg in &stmt.args {
|
for arg in &stmt.args {
|
||||||
let builder_arg = self.lower_statement_arg_to_builder(arg)?;
|
let builder_arg = Self::lower_statement_arg_to_builder(arg)?;
|
||||||
builder = builder.arg(builder_arg);
|
builder = builder.arg(builder_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,13 +380,10 @@ impl<'a> Lowerer<'a> {
|
||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_statement_arg_to_builder(
|
fn lower_statement_arg_to_builder(arg: &StatementTmplArg) -> Result<BuilderArg, LoweringError> {
|
||||||
&self,
|
|
||||||
arg: &StatementTmplArg,
|
|
||||||
) -> Result<BuilderArg, LoweringError> {
|
|
||||||
match arg {
|
match arg {
|
||||||
StatementTmplArg::Literal(lit) => {
|
StatementTmplArg::Literal(lit) => {
|
||||||
let value = self.lower_literal(lit)?;
|
let value = Self::lower_literal(lit)?;
|
||||||
Ok(BuilderArg::Literal(value))
|
Ok(BuilderArg::Literal(value))
|
||||||
}
|
}
|
||||||
StatementTmplArg::Wildcard(id) => {
|
StatementTmplArg::Wildcard(id) => {
|
||||||
|
|
@ -403,7 +400,7 @@ impl<'a> Lowerer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_literal(&self, lit: &LiteralValue) -> Result<middleware::Value, LoweringError> {
|
fn lower_literal(lit: &LiteralValue) -> Result<middleware::Value, LoweringError> {
|
||||||
let value = match lit {
|
let value = match lit {
|
||||||
LiteralValue::Int(i) => middleware::Value::from(i.value),
|
LiteralValue::Int(i) => middleware::Value::from(i.value),
|
||||||
LiteralValue::Bool(b) => middleware::Value::from(b.value),
|
LiteralValue::Bool(b) => middleware::Value::from(b.value),
|
||||||
|
|
@ -413,15 +410,15 @@ impl<'a> Lowerer<'a> {
|
||||||
LiteralValue::SecretKey(sk) => middleware::Value::from(sk.secret_key.clone()),
|
LiteralValue::SecretKey(sk) => middleware::Value::from(sk.secret_key.clone()),
|
||||||
LiteralValue::Array(a) => {
|
LiteralValue::Array(a) => {
|
||||||
let elements: Result<Vec<_>, _> =
|
let elements: Result<Vec<_>, _> =
|
||||||
a.elements.iter().map(|e| self.lower_literal(e)).collect();
|
a.elements.iter().map(Self::lower_literal).collect();
|
||||||
let array = containers::Array::new(self.params.max_depth_mt_containers, elements?)?;
|
let array = containers::Array::new(elements?);
|
||||||
middleware::Value::from(array)
|
middleware::Value::from(array)
|
||||||
}
|
}
|
||||||
LiteralValue::Set(s) => {
|
LiteralValue::Set(s) => {
|
||||||
let elements: Result<Vec<_>, _> =
|
let elements: Result<Vec<_>, _> =
|
||||||
s.elements.iter().map(|e| self.lower_literal(e)).collect();
|
s.elements.iter().map(Self::lower_literal).collect();
|
||||||
let set_values: std::collections::HashSet<_> = elements?.into_iter().collect();
|
let set_values: std::collections::HashSet<_> = elements?.into_iter().collect();
|
||||||
let set = containers::Set::new(self.params.max_depth_mt_containers, set_values)?;
|
let set = containers::Set::new(set_values);
|
||||||
middleware::Value::from(set)
|
middleware::Value::from(set)
|
||||||
}
|
}
|
||||||
LiteralValue::Dict(d) => {
|
LiteralValue::Dict(d) => {
|
||||||
|
|
@ -430,13 +427,12 @@ impl<'a> Lowerer<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pair| {
|
.map(|pair| {
|
||||||
let key = middleware::Key::from(pair.key.value.as_str());
|
let key = middleware::Key::from(pair.key.value.as_str());
|
||||||
let value = self.lower_literal(&pair.value)?;
|
let value = Self::lower_literal(&pair.value)?;
|
||||||
Ok((key, value))
|
Ok((key, value))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let dict_map: std::collections::HashMap<_, _> = pairs?.into_iter().collect();
|
let dict_map: std::collections::HashMap<_, _> = pairs?.into_iter().collect();
|
||||||
let dict =
|
let dict = containers::Dictionary::new(dict_map);
|
||||||
containers::Dictionary::new(self.params.max_depth_mt_containers, dict_map)?;
|
|
||||||
middleware::Value::from(dict)
|
middleware::Value::from(dict)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,34 +22,30 @@ pub struct Dictionary {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
#[schemars(skip)]
|
#[schemars(skip)]
|
||||||
mt: MerkleTree,
|
mt: MerkleTree,
|
||||||
max_depth: usize,
|
|
||||||
#[serde(serialize_with = "ordered_map")]
|
#[serde(serialize_with = "ordered_map")]
|
||||||
kvs: HashMap<Key, Value>,
|
kvs: HashMap<Key, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! dict {
|
macro_rules! dict {
|
||||||
($max_depth:expr, { $($key:expr => $val:expr),* , }) => (
|
({ $($key:expr => $val:expr),* , }) => (
|
||||||
$crate::dict!($max_depth, { $($key => $val),* })
|
$crate::dict!({ $($key => $val),* })
|
||||||
);
|
);
|
||||||
($max_depth:expr, { $($key:expr => $val:expr),* }) => ({
|
({ $($key:expr => $val:expr),* }) => ({
|
||||||
let mut map = ::std::collections::HashMap::new();
|
let mut map = ::std::collections::HashMap::new();
|
||||||
$( map.insert($crate::middleware::Key::from($key), $crate::middleware::Value::from($val)); )*
|
$( map.insert($crate::middleware::Key::from($key), $crate::middleware::Value::from($val)); )*
|
||||||
$crate::middleware::containers::Dictionary::new($max_depth, map)
|
$crate::middleware::containers::Dictionary::new( map)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dictionary {
|
impl Dictionary {
|
||||||
/// max_depth determines the depth of the underlying MerkleTree, allowing to
|
pub fn new(kvs: HashMap<Key, Value>) -> Self {
|
||||||
/// store 2^max_depth elements in the Dictionary
|
|
||||||
pub fn new(max_depth: usize, kvs: HashMap<Key, Value>) -> Result<Self> {
|
|
||||||
let kvs_raw: HashMap<RawValue, RawValue> =
|
let kvs_raw: HashMap<RawValue, RawValue> =
|
||||||
kvs.iter().map(|(k, v)| (k.raw(), v.raw())).collect();
|
kvs.iter().map(|(k, v)| (k.raw(), v.raw())).collect();
|
||||||
Ok(Self {
|
Self {
|
||||||
mt: MerkleTree::new(max_depth, &kvs_raw)?,
|
mt: MerkleTree::new(&kvs_raw),
|
||||||
max_depth,
|
|
||||||
kvs,
|
kvs,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
pub fn commitment(&self) -> Hash {
|
pub fn commitment(&self) -> Hash {
|
||||||
self.mt.root()
|
self.mt.root()
|
||||||
|
|
@ -82,46 +78,21 @@ impl Dictionary {
|
||||||
self.kvs.remove(key);
|
self.kvs.remove(key);
|
||||||
Ok(mtp)
|
Ok(mtp)
|
||||||
}
|
}
|
||||||
pub fn verify(
|
pub fn verify(root: Hash, proof: &MerkleProof, key: &Key, value: &Value) -> Result<()> {
|
||||||
max_depth: usize,
|
|
||||||
root: Hash,
|
|
||||||
proof: &MerkleProof,
|
|
||||||
key: &Key,
|
|
||||||
value: &Value,
|
|
||||||
) -> Result<()> {
|
|
||||||
let key = key.raw();
|
let key = key.raw();
|
||||||
Ok(MerkleTree::verify(
|
Ok(MerkleTree::verify(root, proof, &key, &value.raw())?)
|
||||||
max_depth,
|
|
||||||
root,
|
|
||||||
proof,
|
|
||||||
&key,
|
|
||||||
&value.raw(),
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
pub fn verify_nonexistence(
|
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, key: &Key) -> Result<()> {
|
||||||
max_depth: usize,
|
|
||||||
root: Hash,
|
|
||||||
proof: &MerkleProof,
|
|
||||||
key: &Key,
|
|
||||||
) -> Result<()> {
|
|
||||||
let key = key.raw();
|
let key = key.raw();
|
||||||
Ok(MerkleTree::verify_nonexistence(
|
Ok(MerkleTree::verify_nonexistence(root, proof, &key)?)
|
||||||
max_depth, root, proof, &key,
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
pub fn verify_state_transition(
|
pub fn verify_state_transition(proof: &MerkleTreeStateTransitionProof) -> Result<()> {
|
||||||
max_depth: usize,
|
MerkleTree::verify_state_transition(proof).map_err(|e| e.into())
|
||||||
proof: &MerkleTreeStateTransitionProof,
|
|
||||||
) -> Result<()> {
|
|
||||||
MerkleTree::verify_state_transition(max_depth, proof).map_err(|e| e.into())
|
|
||||||
}
|
}
|
||||||
// TODO: Rename to dict to be consistent maybe?
|
// TODO: Rename to dict to be consistent maybe?
|
||||||
pub fn kvs(&self) -> &HashMap<Key, Value> {
|
pub fn kvs(&self) -> &HashMap<Key, Value> {
|
||||||
&self.kvs
|
&self.kvs
|
||||||
}
|
}
|
||||||
pub fn max_depth(&self) -> usize {
|
|
||||||
self.max_depth
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Dictionary {
|
impl PartialEq for Dictionary {
|
||||||
|
|
@ -140,10 +111,9 @@ impl<'de> Deserialize<'de> for Dictionary {
|
||||||
struct Aux {
|
struct Aux {
|
||||||
#[serde(serialize_with = "ordered_map")]
|
#[serde(serialize_with = "ordered_map")]
|
||||||
kvs: HashMap<Key, Value>,
|
kvs: HashMap<Key, Value>,
|
||||||
max_depth: usize,
|
|
||||||
}
|
}
|
||||||
let aux = Aux::deserialize(deserializer)?;
|
let aux = Aux::deserialize(deserializer)?;
|
||||||
Dictionary::new(aux.max_depth, aux.kvs).map_err(serde::de::Error::custom)
|
Ok(Dictionary::new(aux.kvs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,15 +125,12 @@ pub struct Set {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
#[schemars(skip)]
|
#[schemars(skip)]
|
||||||
mt: MerkleTree,
|
mt: MerkleTree,
|
||||||
max_depth: usize,
|
|
||||||
#[serde(serialize_with = "ordered_set")]
|
#[serde(serialize_with = "ordered_set")]
|
||||||
set: HashSet<Value>,
|
set: HashSet<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Set {
|
impl Set {
|
||||||
/// max_depth determines the depth of the underlying MerkleTree, allowing to
|
pub fn new(set: HashSet<Value>) -> Self {
|
||||||
/// store 2^max_depth elements in the Array
|
|
||||||
pub fn new(max_depth: usize, set: HashSet<Value>) -> Result<Self> {
|
|
||||||
let kvs_raw: HashMap<RawValue, RawValue> = set
|
let kvs_raw: HashMap<RawValue, RawValue> = set
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
|
|
@ -171,11 +138,10 @@ impl Set {
|
||||||
(rv, rv)
|
(rv, rv)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(Self {
|
Self {
|
||||||
mt: MerkleTree::new(max_depth, &kvs_raw)?,
|
mt: MerkleTree::new(&kvs_raw),
|
||||||
max_depth,
|
|
||||||
set,
|
set,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
pub fn commitment(&self) -> Hash {
|
pub fn commitment(&self) -> Hash {
|
||||||
self.mt.root()
|
self.mt.root()
|
||||||
|
|
@ -203,33 +169,20 @@ impl Set {
|
||||||
self.set.remove(value);
|
self.set.remove(value);
|
||||||
Ok(mtp)
|
Ok(mtp)
|
||||||
}
|
}
|
||||||
pub fn verify(max_depth: usize, root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
|
pub fn verify(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
|
||||||
let rv = value.raw();
|
let rv = value.raw();
|
||||||
Ok(MerkleTree::verify(max_depth, root, proof, &rv, &rv)?)
|
Ok(MerkleTree::verify(root, proof, &rv, &rv)?)
|
||||||
}
|
}
|
||||||
pub fn verify_nonexistence(
|
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
|
||||||
max_depth: usize,
|
|
||||||
root: Hash,
|
|
||||||
proof: &MerkleProof,
|
|
||||||
value: &Value,
|
|
||||||
) -> Result<()> {
|
|
||||||
let rv = value.raw();
|
let rv = value.raw();
|
||||||
Ok(MerkleTree::verify_nonexistence(
|
Ok(MerkleTree::verify_nonexistence(root, proof, &rv)?)
|
||||||
max_depth, root, proof, &rv,
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
pub fn verify_state_transition(
|
pub fn verify_state_transition(proof: &MerkleTreeStateTransitionProof) -> Result<()> {
|
||||||
max_depth: usize,
|
MerkleTree::verify_state_transition(proof).map_err(|e| e.into())
|
||||||
proof: &MerkleTreeStateTransitionProof,
|
|
||||||
) -> Result<()> {
|
|
||||||
MerkleTree::verify_state_transition(max_depth, proof).map_err(|e| e.into())
|
|
||||||
}
|
}
|
||||||
pub fn set(&self) -> &HashSet<Value> {
|
pub fn set(&self) -> &HashSet<Value> {
|
||||||
&self.set
|
&self.set
|
||||||
}
|
}
|
||||||
pub fn max_depth(&self) -> usize {
|
|
||||||
self.max_depth
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Set {
|
impl PartialEq for Set {
|
||||||
|
|
@ -248,10 +201,9 @@ impl<'de> Deserialize<'de> for Set {
|
||||||
struct Aux {
|
struct Aux {
|
||||||
#[serde(serialize_with = "ordered_set")]
|
#[serde(serialize_with = "ordered_set")]
|
||||||
set: HashSet<Value>,
|
set: HashSet<Value>,
|
||||||
max_depth: usize,
|
|
||||||
}
|
}
|
||||||
let aux = Aux::deserialize(deserializer)?;
|
let aux = Aux::deserialize(deserializer)?;
|
||||||
Set::new(aux.max_depth, aux.set).map_err(serde::de::Error::custom)
|
Ok(Set::new(aux.set))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,25 +216,21 @@ pub struct Array {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
#[schemars(skip)]
|
#[schemars(skip)]
|
||||||
mt: MerkleTree,
|
mt: MerkleTree,
|
||||||
max_depth: usize,
|
|
||||||
array: Vec<Value>,
|
array: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Array {
|
impl Array {
|
||||||
/// max_depth determines the depth of the underlying MerkleTree, allowing to
|
pub fn new(array: Vec<Value>) -> Self {
|
||||||
/// store 2^max_depth elements in the Array
|
|
||||||
pub fn new(max_depth: usize, array: Vec<Value>) -> Result<Self> {
|
|
||||||
let kvs_raw: HashMap<RawValue, RawValue> = array
|
let kvs_raw: HashMap<RawValue, RawValue> = array
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, e)| (RawValue::from(i as i64), e.raw()))
|
.map(|(i, e)| (RawValue::from(i as i64), e.raw()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Self {
|
Self {
|
||||||
mt: MerkleTree::new(max_depth, &kvs_raw)?,
|
mt: MerkleTree::new(&kvs_raw),
|
||||||
max_depth,
|
|
||||||
array,
|
array,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
pub fn commitment(&self) -> Hash {
|
pub fn commitment(&self) -> Hash {
|
||||||
self.mt.root()
|
self.mt.root()
|
||||||
|
|
@ -302,33 +250,20 @@ impl Array {
|
||||||
self.array[i] = value.clone();
|
self.array[i] = value.clone();
|
||||||
Ok(mtp)
|
Ok(mtp)
|
||||||
}
|
}
|
||||||
pub fn verify(
|
pub fn verify(root: Hash, proof: &MerkleProof, i: usize, value: &Value) -> Result<()> {
|
||||||
max_depth: usize,
|
|
||||||
root: Hash,
|
|
||||||
proof: &MerkleProof,
|
|
||||||
i: usize,
|
|
||||||
value: &Value,
|
|
||||||
) -> Result<()> {
|
|
||||||
Ok(MerkleTree::verify(
|
Ok(MerkleTree::verify(
|
||||||
max_depth,
|
|
||||||
root,
|
root,
|
||||||
proof,
|
proof,
|
||||||
&RawValue::from(i as i64),
|
&RawValue::from(i as i64),
|
||||||
&value.raw(),
|
&value.raw(),
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
pub fn verify_state_transition(
|
pub fn verify_state_transition(proof: &MerkleTreeStateTransitionProof) -> Result<()> {
|
||||||
max_depth: usize,
|
MerkleTree::verify_state_transition(proof).map_err(|e| e.into())
|
||||||
proof: &MerkleTreeStateTransitionProof,
|
|
||||||
) -> Result<()> {
|
|
||||||
MerkleTree::verify_state_transition(max_depth, proof).map_err(|e| e.into())
|
|
||||||
}
|
}
|
||||||
pub fn array(&self) -> &[Value] {
|
pub fn array(&self) -> &[Value] {
|
||||||
&self.array
|
&self.array
|
||||||
}
|
}
|
||||||
pub fn max_depth(&self) -> usize {
|
|
||||||
self.max_depth
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Array {
|
impl PartialEq for Array {
|
||||||
|
|
@ -346,9 +281,8 @@ impl<'de> Deserialize<'de> for Array {
|
||||||
#[derive(Deserialize, JsonSchema)]
|
#[derive(Deserialize, JsonSchema)]
|
||||||
struct Aux {
|
struct Aux {
|
||||||
array: Vec<Value>,
|
array: Vec<Value>,
|
||||||
max_depth: usize,
|
|
||||||
}
|
}
|
||||||
let aux = Aux::deserialize(deserializer)?;
|
let aux = Aux::deserialize(deserializer)?;
|
||||||
Array::new(aux.max_depth, aux.array).map_err(serde::de::Error::custom)
|
Ok(Array::new(aux.array))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -524,13 +524,13 @@ mod tests {
|
||||||
)?],
|
)?],
|
||||||
);
|
);
|
||||||
|
|
||||||
let d0 = dict!(32, {
|
let d0 = dict!({
|
||||||
"a" => 10,
|
"a" => 10,
|
||||||
})?;
|
});
|
||||||
let d1 = dict!(32, {
|
let d1 = dict!({
|
||||||
"b" => 15,
|
"b" => 15,
|
||||||
"c" => 17,
|
"c" => 17,
|
||||||
})?;
|
});
|
||||||
let custom_statement = Statement::Custom(
|
let custom_statement = Statement::Custom(
|
||||||
CustomPredicateRef::new(cust_pred_batch.clone(), 0),
|
CustomPredicateRef::new(cust_pred_batch.clone(), 0),
|
||||||
vec![Value::from(d0.clone())],
|
vec![Value::from(d0.clone())],
|
||||||
|
|
|
||||||
|
|
@ -446,24 +446,13 @@ impl Operation {
|
||||||
let root = val(root_v, root_s)?;
|
let root = val(root_v, root_s)?;
|
||||||
let key = val(key_v, key_s)?;
|
let key = val(key_v, key_s)?;
|
||||||
let value = val(val_v, val_s)?;
|
let value = val(val_v, val_s)?;
|
||||||
MerkleTree::verify(
|
MerkleTree::verify(root.raw().into(), pf, &key.raw(), &value.raw())?;
|
||||||
params.max_depth_mt_containers,
|
|
||||||
root.raw().into(),
|
|
||||||
pf,
|
|
||||||
&key.raw(),
|
|
||||||
&value.raw(),
|
|
||||||
)?;
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(Self::NotContainsFromEntries(root_s, key_s, pf), NotContains(root_v, key_v)) => {
|
(Self::NotContainsFromEntries(root_s, key_s, pf), NotContains(root_v, key_v)) => {
|
||||||
let root = val(root_v, root_s)?;
|
let root = val(root_v, root_s)?;
|
||||||
let key = val(key_v, key_s)?;
|
let key = val(key_v, key_s)?;
|
||||||
MerkleTree::verify_nonexistence(
|
MerkleTree::verify_nonexistence(root.raw().into(), pf, &key.raw())?;
|
||||||
params.max_depth_mt_containers,
|
|
||||||
root.raw().into(),
|
|
||||||
pf,
|
|
||||||
&key.raw(),
|
|
||||||
)?;
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
@ -507,7 +496,7 @@ impl Operation {
|
||||||
"The provided Merkle tree state transition proof does not match the claim."
|
"The provided Merkle tree state transition proof does not match the claim."
|
||||||
.into(),
|
.into(),
|
||||||
))?;
|
))?;
|
||||||
MerkleTree::verify_state_transition(params.max_depth_mt_containers, pf)?;
|
MerkleTree::verify_state_transition(pf)?;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
@ -528,7 +517,7 @@ impl Operation {
|
||||||
"The provided Merkle tree state transition proof does not match the claim."
|
"The provided Merkle tree state transition proof does not match the claim."
|
||||||
.into(),
|
.into(),
|
||||||
))?;
|
))?;
|
||||||
MerkleTree::verify_state_transition(params.max_depth_mt_containers, pf)?;
|
MerkleTree::verify_state_transition(pf)?;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
@ -547,7 +536,7 @@ impl Operation {
|
||||||
"The provided Merkle tree state transition proof does not match the claim."
|
"The provided Merkle tree state transition proof does not match the claim."
|
||||||
.into(),
|
.into(),
|
||||||
))?;
|
))?;
|
||||||
MerkleTree::verify_state_transition(params.max_depth_mt_containers, pf)?;
|
MerkleTree::verify_state_transition(pf)?;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(Self::Custom(CustomPredicateRef { batch, index }, args), Custom(cpr, s_args))
|
(Self::Custom(CustomPredicateRef { batch, index }, args), Custom(cpr, s_args))
|
||||||
|
|
@ -815,7 +804,7 @@ mod tests {
|
||||||
let kvs = (0..10)
|
let kvs = (0..10)
|
||||||
.map(|i| (hash_value(&i.into()).into(), i.into()))
|
.map(|i| (hash_value(&i.into()).into(), i.into()))
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
let mt = MerkleTree::new(params.max_depth_mt_containers, &kvs)?;
|
let mt = MerkleTree::new(&kvs);
|
||||||
let root = mt.root();
|
let root = mt.root();
|
||||||
|
|
||||||
// Check existence proofs
|
// Check existence proofs
|
||||||
|
|
@ -873,7 +862,7 @@ mod tests {
|
||||||
let kvs = (0..10)
|
let kvs = (0..10)
|
||||||
.map(|i| (hash_value(&i.into()).into(), i.into()))
|
.map(|i| (hash_value(&i.into()).into(), i.into()))
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
let mut mt = MerkleTree::new(params.max_depth_mt_containers, &kvs)?;
|
let mut mt = MerkleTree::new(&kvs);
|
||||||
|
|
||||||
// Check insertion proofs
|
// Check insertion proofs
|
||||||
(11..20)
|
(11..20)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue