-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
201 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Binary Merkle Tree | ||
|
||
A Binary Merkle Tree is a **dense** Merkle Tree where each leaf node is **full** (non-zero). The [example](./README.md) of the vector with elements `[m, y, v, e, c, t, o, r]` is an example of a Dense Merkle Tree for a tree of depth 3. | ||
|
||
## See Also | ||
|
||
- [PSE zk-kit: Binary Merkle Root](https://github.com/privacy-scaling-explorations/zk-kit.circom/tree/main/packages/binary-merkle-root) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Complete Binary Merkle Tree | ||
|
||
A **Complete Binary Merkle Tree** is a Merkle Tree that does not necessarily have $2^n-1$ nodes, but instead it is optimized to use a few nodes as possible, doing so with only the exception of the last node possibly being empty. | ||
|
||
## See Also | ||
|
||
- [Nervos Network](https://www.nervos.org/)'s CBMT implementation: <https://github.com/nervosnetwork/merkle-tree> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Incremential Merkle Tree | ||
|
||
An Incremential Merkle Tree is a tree that one can start completely empty (all-zeros) with a fixed number of nodes, and then allow addition & removal of nodes to the tree. | ||
|
||
## See Also | ||
|
||
- [PSE zk-kit: Incremental Merkle Tree](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/imt) | ||
- [PSE zk-kit: Lean Incremental Merkle Tree](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/lean-imt) | ||
- [HerodotusDev's Accumulators IMT](https://github.com/HerodotusDev/accumulators/blob/main/packages/incremental-merkle-tree/README.md) | ||
- [RareSkills Tornado Cash Line-by-Line](https://www.rareskills.io/post/how-does-tornado-cash-work) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Merkle Mountain Range | ||
|
||
TODO: !!! | ||
|
||
## See Also | ||
|
||
- [HerodotusDev's Accumulators MMR](https://github.com/HerodotusDev/accumulators/tree/main/packages/merkle-mountain-range) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
# Sparse Merkle Tree | ||
|
||
In our description of the Merkle Tree, we had a binary-tree with 8 leaf nodes, and we had filled all of them with elements of a vector $\vec{v} = [m, y, v, e, c, t, o, r]$. What if we did not have data to fill the entire leaves? | ||
What if we don't even know the size of the tree in advance? This is where **Sparse Merkle Trees** come in. It is like an [**Incremential Merkle Tree**](./imt.md) in the sense that we can update the tree by adding / removing nodes, but in the case of a Sparse Merkle Tree the size of the tree is not known ahead of time! | ||
|
||
A Sparse Merkle Tree allow us to create Merkle Trees where the leaf nodes are not entirely filled, and one can create either an inclusion proof or exclusion proof for an element in the tree without revealing the entire tree. | ||
|
||
- **Inclusion proof** shows that an element is in the tree, as we discussed while describing Merkle Trees. | ||
- **Exclusion proof** shows that an element is NOT in the tree. This is possible with a Sparse Merkle Tree because nodes | ||
|
||
## See Also | ||
|
||
- [Tochicool's SMT](https://github.com/tochicool/sparse-merkle-trees#readme) | ||
- [Efficient Sparse Merkle Trees](https://eprint.iacr.org/2016/683.pdf) by Rasmus Dahlberg, Tobias Pulls, and Roel Peeters. | ||
- Iden3 (authors of Circom) has a nice publication on Merkle Trees: [Sparse Merkle Trees](https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf) by Jordi Baylina and Marta Belles. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
pragma circom 2.1.0; | ||
|
||
include "circomlib/circuits/poseidon.circom"; | ||
|
||
// Binary Merkle Tree | ||
// | ||
// Parameters: | ||
// - n: depth of the tree such that number of leaves is 2^n | ||
// | ||
// Inputs: | ||
// - leafs: the leaves of the tree | ||
// | ||
// Outputs: | ||
// - root: the root of the tree | ||
// | ||
template BinaryMerkleTree(n) { | ||
assert(n > 0); | ||
var NUM_LEAVES = 1 << n; | ||
var NUM_NODES = (1 << (n+1)) - 1; | ||
signal input leafs[NUM_LEAVES]; | ||
signal output root; | ||
|
||
signal nodes[NUM_NODES]; | ||
|
||
// compute hashes of leaves | ||
for (var i = 0; i < NUM_LEAVES; i++) { | ||
nodes[(NUM_NODES - 1) - i] <== Poseidon(1)([leafs[i]]); | ||
} | ||
|
||
// build the tree from the leaves to the root in reverse | ||
for (var i = NUM_NODES - NUM_LEAVES - 1; i >= 0; i--) { | ||
nodes[i] <== Poseidon(2)([nodes[2*i + 1], nodes[2*i + 2]]); | ||
} | ||
|
||
root <== nodes[0]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// auto-generated by circomkit | ||
pragma circom 2.0.0; | ||
|
||
include "../../merkle-trees/bmt.circom"; | ||
|
||
component main = BinaryMerkleTree(1); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// auto-generated by circomkit | ||
pragma circom 2.0.0; | ||
|
||
include "../../merkle-trees/bmt.circom"; | ||
|
||
component main = BinaryMerkleTree(2); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { poseidon1, poseidon2 } from "poseidon-lite"; | ||
import { circomkit } from "../common"; | ||
import { describe, beforeAll, it } from "bun:test"; | ||
|
||
function binaryMerkleTree(leafs: bigint[]) { | ||
if (leafs.length === 0) { | ||
throw new Error("The number of leafs must be greater than 0"); | ||
} | ||
|
||
const n = Math.ceil(Math.log2(leafs.length)); | ||
if (1 << n !== leafs.length) { | ||
throw new Error("The number of leafs must be a power of 2 " + `${1 << n} != ${leafs.length}`); | ||
} | ||
|
||
const NUM_LEAVES = 1 << n; | ||
const NUM_NODES = (1 << (n + 1)) - 1; | ||
const nodes: bigint[] = new Array(NUM_NODES).fill(0n); | ||
|
||
// compute hashes of leaves | ||
for (let i = 0; i < NUM_LEAVES; i++) { | ||
nodes[NUM_NODES - 1 - i] = poseidon1([leafs[i]]); | ||
} | ||
|
||
// build the tree from the leaves to the root in reverse | ||
for (let i = NUM_NODES - NUM_LEAVES - 1; i >= 0; i--) { | ||
nodes[i] = poseidon2([nodes[2 * i + 1], nodes[2 * i + 2]]); | ||
} | ||
|
||
const root = nodes[0]; | ||
return { leafs, nodes, root }; | ||
} | ||
|
||
describe("binary merkle tree", () => { | ||
it("n = 1", async () => { | ||
const circuit = await circomkit.WitnessTester<["leafs"], ["root"]>("bmt-1", { | ||
file: "merkle-trees/bmt", | ||
template: "BinaryMerkleTree", | ||
dir: "test/merkle-trees", | ||
params: [1], | ||
}); | ||
|
||
const leafs = [123n, 345n]; | ||
const { root } = binaryMerkleTree(leafs); | ||
await circuit.expectPass({ leafs }, { root }); | ||
}); | ||
|
||
it("n = 2", async () => { | ||
const circuit = await circomkit.WitnessTester<["leafs"], ["root"]>("bmt-2", { | ||
file: "merkle-trees/bmt", | ||
template: "BinaryMerkleTree", | ||
dir: "test/merkle-trees", | ||
params: [2], | ||
}); | ||
|
||
const leafs = [123n, 345n, 678n, 981n]; | ||
const { root } = binaryMerkleTree(leafs); | ||
await circuit.expectPass({ leafs }, { root }); | ||
}); | ||
}); |