Skip to content

Commit

Permalink
Use merkle-cbt crate
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Varlakov committed Sep 8, 2021
1 parent 649c46e commit e1460d5
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 46 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
* Implement Try and Increment when converting hash to scalar [#128] \
Improves performance and security of conversion 🔥
* Get rid of deprecated `rust-crypto` dependency [#137]
* Changed the crate providing merkle trees support: `merkle-sha3 v0.1``merkle v1`
* Changed a hash function used by merkle proofs: `keccak256``sha256`
* Merkle trees support is optional: use `merkle-tree` feature to enable it
* Changed the crate providing merkle trees support: `merkle-sha3 v0.1``merkle-cbt v0.3`
* Merkle trees API has been slightly changed
* Merkle trees are generic over hash function (it used to work with keccak256 only)
* Merkle proofs built by previous versions of `curv` are incompatible with latest `curv`

[#128]: https://github.com/ZenGo-X/curv/pull/128
[#137]: https://github.com/ZenGo-X/curv/pull/137
Expand Down
6 changes: 1 addition & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ sha2 = "0.9"
sha3 = "0.9"
old_sha2 = { package = "sha2", version = "0.8" }
zeroize = "1"

# merkle trees support
merkle = { version = "1", optional = true }
ring = { version = "0.16", optional = true }
merkle-cbt = "0.3"

rust-gmp-kzen = { version = "0.5", features = ["serde_support"], optional = true }
num-bigint = { version = "0.4", features = ["serde"], optional = true }
Expand All @@ -62,7 +59,6 @@ proptest-derive = "0.2"

[features]
default = ["rust-gmp-kzen"]
merkle-tree = ["merkle", "ring"]

[package.metadata.docs.rs]
rustdoc-args = [ "--html-in-header", "katex-header.html", "--cfg", "docsrs" ]
105 changes: 69 additions & 36 deletions src/cryptographic_primitives/hashing/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,90 @@

use std::marker::PhantomData;

use merkle::{MerkleTree, Proof};
use ring::digest::SHA256;
use digest::{Digest, Output};
use merkle_cbt::merkle_tree::{Merge, MerkleProof, MerkleTree, CBMT};
use serde::{Deserialize, Serialize};

use crate::cryptographic_primitives::hashing::DigestExt;
use crate::cryptographic_primitives::proofs::ProofError;
use crate::elliptic::curves::{Curve, Point};

pub struct MT256<E: Curve> {
tree: MerkleTree<[u8; 32]>,
_ph: PhantomData<E>,
pub struct MT256<E: Curve, H: Digest> {
tree: MerkleTree<Output<H>, MergeDigest<H>>,
leaves: Vec<Point<E>>,
_ph: PhantomData<fn(E)>,
}

//impl <'a> MT256<'a>{
impl<E: Curve> MT256<E> {
pub fn create_tree(vec: &[Point<E>]) -> MT256<E> {
let vec_bytes = (0..vec.len())
.map(|i| {
let mut array = [0u8; 32];
let bytes = vec[i].to_bytes(false);
array.copy_from_slice(&bytes[0..32]);
array
})
.collect::<Vec<[u8; 32]>>();
let tree = MerkleTree::from_vec(&SHA256, vec_bytes);
impl<E: Curve, H: Digest + Clone> MT256<E, H> {
pub fn create_tree(leaves: Vec<Point<E>>) -> Self {
let hashes = leaves
.iter()
.map(|leaf| H::new().chain_point(leaf).finalize())
.collect::<Vec<_>>();

MT256 {
tree,
tree: CBMT::<Output<H>, MergeDigest<H>>::build_merkle_tree(&hashes),
leaves,
_ph: PhantomData,
}
}

pub fn gen_proof_for_ge(&self, value: &Point<E>) -> Proof<[u8; 32]> {
let mut array = [0u8; 32];
let pk_slice = value.to_bytes(false);
array.copy_from_slice(&pk_slice[0..32]);
self.tree.gen_proof(array).expect("not found in tree")
pub fn build_proof(&self, point: Point<E>) -> Option<Proof<E, H>> {
let index = (0u32..)
.zip(&self.leaves)
.find(|(_, leaf)| **leaf == point)
.map(|(i, _)| i)?;
let proof = self.tree.build_proof(&[index])?;
Some(Proof {
index: proof.indices()[0],
lemmas: proof.lemmas().to_vec(),
point,
})
}

pub fn get_root(&self) -> &Vec<u8> {
MerkleTree::root_hash(&self.tree)
pub fn get_root(&self) -> Output<H> {
self.tree.root()
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(bound(
serialize = "Output<H>: Serialize",
deserialize = "Output<H>: Deserialize<'de>"
))]
pub struct Proof<E: Curve, H: Digest> {
pub index: u32,
pub lemmas: Vec<Output<H>>,
pub point: Point<E>,
}

#[allow(clippy::result_unit_err)]
pub fn validate_proof(proof: &Proof<[u8; 32]>, root: &[u8]) -> Result<(), ()> {
if proof.validate(root) {
impl<E: Curve, H: Digest + Clone> Proof<E, H> {
pub fn verify(&self, root: &Output<H>) -> Result<(), ProofError> {
let leaf = H::new().chain_point(&self.point).finalize();
let valid =
MerkleProof::<Output<H>, MergeDigest<H>>::new(vec![self.index], self.lemmas.clone())
.verify(root, &[leaf]);
if valid {
Ok(())
} else {
Err(())
Err(ProofError)
}
}
}

struct MergeDigest<D>(PhantomData<D>);

impl<D> Merge for MergeDigest<D>
where
D: Digest,
{
type Item = Output<D>;

fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item {
D::new().chain(left).chain(right).finalize()
}
}

#[cfg(test)]
mod tests {
use super::MT256;
Expand All @@ -72,11 +106,10 @@ mod tests {
let ge3: Point<E> = &ge1 + &ge2;
let ge4: Point<E> = &ge1 + &ge3;
let ge_vec = vec![ge1.clone(), ge2, ge3, ge4];
let mt256 = MT256::create_tree(&ge_vec);
let proof1 = mt256.gen_proof_for_ge(&ge1);
let mt256 = MT256::<_, sha3::Keccak256>::create_tree(ge_vec);
let proof1 = mt256.build_proof(ge1).unwrap();
let root = mt256.get_root();
let valid_proof = MT256::<E>::validate_proof(&proof1, root).is_ok();
assert!(valid_proof);
proof1.verify(&root).expect("proof is invalid");
}

test_for_all_curves!(test_mt_functionality_three_leaves);
Expand All @@ -87,9 +120,9 @@ mod tests {
let ge3: Point<E> = &ge1 + &ge2;

let ge_vec = vec![ge1.clone(), ge2, ge3];
let mt256 = MT256::create_tree(&ge_vec);
let proof1 = mt256.gen_proof_for_ge(&ge1);
let mt256 = MT256::<_, sha3::Keccak256>::create_tree(ge_vec);
let proof1 = mt256.build_proof(ge1).unwrap();
let root = mt256.get_root();
assert!(MT256::<E>::validate_proof(&proof1, root).is_ok());
proof1.verify(&root).expect("proof is invalid");
}
}
2 changes: 0 additions & 2 deletions src/cryptographic_primitives/hashing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ pub mod blake2b512;
pub mod hash_sha256;
pub mod hash_sha512;
pub mod hmac_sha512;
#[cfg(feature = "merkle")]
#[cfg_attr(docsrs, doc(cfg(feature = "merkle")))]
pub mod merkle_tree;
pub mod traits;

Expand Down

0 comments on commit e1460d5

Please sign in to comment.