mirror of
https://github.com/tlsnotary/rs-merkle.git
synced 2026-01-08 22:38:07 -05:00
initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "rs-merkle"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
8
src/lib.rs
Normal file
8
src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
mod merkle_tree;
|
||||
mod merkle_proof;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use merkle_tree::MerkleTree;
|
||||
pub use merkle_proof::MerkleProof;
|
||||
1
src/merkle_proof.rs
Normal file
1
src/merkle_proof.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub struct MerkleProof {}
|
||||
95
src/merkle_tree.rs
Normal file
95
src/merkle_tree.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
struct ProofAccumulator {
|
||||
current_layer_indices: number[],
|
||||
proof_hashes: Uint8Array[]
|
||||
}
|
||||
|
||||
pub struct MerkleTree {
|
||||
layers: Vec<Vec<Vec<u8>>>
|
||||
// hash_function: (i: Uint8Array) => Uint8Array;
|
||||
}
|
||||
|
||||
fn concat_and_hash(left: Option<&Vec<u8>>, right: Option<&Vec<u8>>) -> Vec<u8> {
|
||||
// TODO: implement and add hash function
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn get_tree_depth(tree_size: usize) -> u32 {
|
||||
// TODO: implement
|
||||
return 1;
|
||||
}
|
||||
|
||||
impl MerkleTree {
|
||||
fn calculate_parent_layer(&self, nodes: &Vec<Vec<u8>>) -> Vec<Vec<u8>> {
|
||||
let parent_layer_nodes_count = Math.ceil(nodes.length / 2);
|
||||
let mut layer = Vec::new();
|
||||
|
||||
for i in 0..parent_layer_nodes_count {
|
||||
layer.push(concat_and_hash(nodes.get(i * 2), nodes.get(i * 2 + 1)));
|
||||
}
|
||||
|
||||
layer
|
||||
}
|
||||
|
||||
fn create_tree(&self, leaf_hashes: Vec<Vec<u8>>) -> Vec<Vec<Vec<u8>>> {
|
||||
let tree_depth = get_tree_depth(leaf_hashes.len());
|
||||
let range = 0..tree_depth;
|
||||
let mut tree = vec![leaf_hashes];
|
||||
range.fold(&mut tree, |&mut tre, layer_index| tre.push(&self.calculate_parent_layer(tree.get(layer_index))));
|
||||
tree
|
||||
}
|
||||
|
||||
pub fn new(leafHashes: Uint8Array[], hashFunction: (i: Uint8Array) => Uint8Array) {
|
||||
this.hashFunction = hashFunction;
|
||||
this.layers = this.createTree(leafHashes);
|
||||
}
|
||||
|
||||
// Public methods
|
||||
|
||||
pub fn get_root(): Uint8Array {
|
||||
return this.layers[this.layers.length - 1][0];
|
||||
}
|
||||
|
||||
pub fn get_depth(): number {
|
||||
return this.layers.length - 1;
|
||||
}
|
||||
|
||||
pub fn get_proof(leafIndices: number[]): MerkleProof {
|
||||
// Proof consists of all siblings hashes that aren't in the set we're trying to prove
|
||||
// 1. Get all sibling indices. Those are the indices we need to get to the root
|
||||
// 2. Filter all nodes that doesn't require an additional hash
|
||||
// 3. Get all hashes for indices from step 2
|
||||
// 4. Remove empty spaces (the leftmost nodes that do not have anything to the right)7
|
||||
const { proofHashes: proof } = this.layers.reduce((
|
||||
{ currentLayerIndices, proofHashes }: ProofAccumulator, treeLayer,
|
||||
) => ({
|
||||
currentLayerIndices: getParentIndices(currentLayerIndices),
|
||||
proofHashes: [
|
||||
...proofHashes,
|
||||
...currentLayerIndices
|
||||
.map(getSiblingIndex)
|
||||
.filter((siblingIndex) => !currentLayerIndices.includes(siblingIndex))
|
||||
.map((index) => treeLayer[index])
|
||||
.filter((proofHash) => !!proofHash)],
|
||||
}),
|
||||
{
|
||||
currentLayerIndices: leafIndices,
|
||||
proofHashes: [],
|
||||
});
|
||||
|
||||
return new MerkleProof(proof, this.hashFunction);
|
||||
}
|
||||
|
||||
getLayers(): Uint8Array[][] {
|
||||
return this.layers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tree layers as an array of hex hashes
|
||||
*
|
||||
* @return {string[][]}
|
||||
*/
|
||||
pub fn get_hex_layers(): string[][] {
|
||||
return this.getLayers().map((layer) => layer.map(uint8ArrayToHex));
|
||||
}
|
||||
}
|
||||
}
|
||||
0
src/tests/mod.rs
Normal file
0
src/tests/mod.rs
Normal file
Reference in New Issue
Block a user