Skip to content

Commit

Permalink
Merge pull request #72 from privacy-scaling-explorations/chore/smt
Browse files Browse the repository at this point in the history
Rename `sparse-merkle-tree` package to `smt`
  • Loading branch information
cedoor authored Nov 27, 2023
2 parents 6bba5b0 + 1fe9004 commit 97cf1e6
Show file tree
Hide file tree
Showing 20 changed files with 1,570 additions and 1,301 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,29 +115,29 @@
</tr>
<tr>
<td>
<a href="https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/sparse-merkle-tree">
@zk-kit/sparse-merkle-tree
<a href="https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/smt">
@zk-kit/smt
</a>
<a href="https://zkkit.pse.dev/modules/_zk_kit_sparse_merkle_tree.html">
<a href="https://zkkit.pse.dev/modules/_zk_kit_smt.html">
(docs)
</a>
</td>
<td>
<!-- NPM version -->
<a href="https://npmjs.org/package/@zk-kit/sparse-merkle-tree">
<img src="https://img.shields.io/npm/v/@zk-kit/sparse-merkle-tree.svg?style=flat-square" alt="NPM version" />
<a href="https://npmjs.org/package/@zk-kit/smt">
<img src="https://img.shields.io/npm/v/@zk-kit/smt.svg?style=flat-square" alt="NPM version" />
</a>
</td>
<td>
<!-- Downloads -->
<a href="https://npmjs.org/package/@zk-kit/sparse-merkle-tree">
<img src="https://img.shields.io/npm/dm/@zk-kit/sparse-merkle-tree.svg?style=flat-square" alt="Downloads" />
<a href="https://npmjs.org/package/@zk-kit/smt">
<img src="https://img.shields.io/npm/dm/@zk-kit/smt.svg?style=flat-square" alt="Downloads" />
</a>
</td>
<td>
<!-- Size -->
<a href="https://bundlephobia.com/package/@zk-kit/sparse-merkle-tree">
<img src="https://img.shields.io/bundlephobia/minzip/@zk-kit/sparse-merkle-tree" alt="npm bundle size (scoped)" />
<a href="https://bundlephobia.com/package/@zk-kit/smt">
<img src="https://img.shields.io/bundlephobia/minzip/@zk-kit/smt" alt="npm bundle size (scoped)" />
</a>
</td>
</tr>
Expand Down Expand Up @@ -286,9 +286,9 @@ ZK-kit provides a set of pre-configured development tools. All you have to deal

```bash
cd zk-kit
cp -r packages/sparse-merkle-tree packages/my-package
cp -r packages/smt packages/my-package
cd packages/my-package && rm -fr node_modules dist
grep -r -l "sparse-merkle-tree" . | xargs sed -i 's/sparse-merkle-tree/my-package/'
grep -r -l "smt" . | xargs sed -i 's/smt/my-package/'
# Update the remaining description/usage sections, and write your code in the src & tests folders!
```

Expand Down
2 changes: 1 addition & 1 deletion packages/imt.sol/contracts/BinaryIMT.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
pragma solidity ^0.8.0;

import {PoseidonT3} from "poseidon-solidity/PoseidonT3.sol";

Expand Down
2 changes: 2 additions & 0 deletions packages/imt.sol/contracts/LazyIMT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ library LazyIMT {
}

function root(LazyIMTData storage self) public view returns (uint256) {
// this will always short circuit if self.numberOfLeaves == 0
uint40 numberOfLeaves = self.numberOfLeaves;
// dynamically determine a depth
uint8 depth = 1;
Expand Down Expand Up @@ -107,6 +108,7 @@ library LazyIMT {
} else {
levels[0] = defaultZero(0);
}

for (uint8 i = 0; i < depth; ) {
if (index & 1 == 0) {
levels[i + 1] = PoseidonT3.hash([levels[i], defaultZero(i)]);
Expand Down
2 changes: 1 addition & 1 deletion packages/imt.sol/contracts/QuinaryIMT.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
pragma solidity ^0.8.0;

import {PoseidonT6} from "poseidon-solidity/PoseidonT6.sol";

Expand Down
309 changes: 309 additions & 0 deletions packages/imt.sol/test/QuinIMT.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
//import { expect } from "chai"

Check failure on line 1 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//import { Contract } from "ethers"

Check failure on line 2 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//import { ethers, run } from "hardhat"

Check failure on line 3 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//import { createTree } from "./utils"

Check failure on line 4 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment

//[> eslint-disable jest/valid-expect <]

Check failure on line 6 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//describe("IncrementalQuinTreeTest", () => {

Check warning on line 7 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented

Check failure on line 7 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//let contract: Contract

Check failure on line 8 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment

//const treeId = ethers.utils.formatBytes32String("treeId")

Check failure on line 10 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//const leaf = BigInt(1)

Check failure on line 11 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment
//const depth = 8

Check failure on line 12 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Expected exception block, space or tab after '//' in comment

//before(async () => {
//contract = await run("deploy:iqt-test", { logs: false })
//})

//it("Should not create a tree with a depth > 32", async () => {

Check warning on line 18 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const transaction = contract.createTree(treeId, 33)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: tree depth must be between 1 and 32")
//})

//it("Should create a tree", async () => {

Check warning on line 24 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const transaction = contract.createTree(treeId, depth)

//await expect(transaction).to.emit(contract, "TreeCreated").withArgs(treeId, depth)
//})

//it("Should not create a tree with an existing id", async () => {

Check warning on line 30 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const transaction = contract.createTree(treeId, depth)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTreeTest: tree already exists")
//})

//it("Should not insert a leaf if the tree does not exist", async () => {

Check warning on line 36 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const treeId = ethers.utils.formatBytes32String("treeId2")

//const transaction = contract.insertLeaf(treeId, leaf)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTreeTest: tree does not exist")
//})

//it("Should not insert a leaf if its value is > SNARK_SCALAR_FIELD", async () => {

Check warning on line 44 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const leaf = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495618")

//const transaction = contract.insertLeaf(treeId, leaf)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: leaf must be < SNARK_SCALAR_FIELD")
//})

//it("Should insert a leaf in a tree", async () => {

Check warning on line 52 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const tree = createTree(depth, 1, 5)
//const transaction = contract.insertLeaf(treeId, leaf)

//await expect(transaction).to.emit(contract, "LeafInserted").withArgs(treeId, leaf, tree.root)
//})

//it("Should insert 6 leaves in a tree", async () => {

Check warning on line 59 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const treeId = ethers.utils.formatBytes32String("tree2")
//await contract.createTree(treeId, depth)
//const tree = createTree(depth, 0, 5)

//for (let i = 0; i < 6; i += 1) {
//tree.insert(BigInt(i + 1))
//const transaction = contract.insertLeaf(treeId, BigInt(i + 1))

//await expect(transaction)
//.to.emit(contract, "LeafInserted")
//.withArgs(treeId, BigInt(i + 1), tree.root)
//}
//})

//it("Should not insert a leaf if the tree is full", async () => {

Check warning on line 74 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const treeId = ethers.utils.formatBytes32String("tinyTree")

//await contract.createTree(treeId, 1)
//await contract.insertLeaf(treeId, leaf)
//await contract.insertLeaf(treeId, leaf)
//await contract.insertLeaf(treeId, leaf)
//await contract.insertLeaf(treeId, leaf)
//await contract.insertLeaf(treeId, leaf)

//const transaction = contract.insertLeaf(treeId, leaf)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: tree is full")
//})

//it("Should not update a leaf if the tree does not exist", async () => {

Check warning on line 89 in packages/imt.sol/test/QuinIMT.ts

View workflow job for this annotation

GitHub Actions / style

Some tests seem to be commented
//const treeId = ethers.utils.formatBytes32String("none")

//const transaction = contract.updateLeaf(treeId, leaf, leaf, [[0, 1, 2, 3]], [0])

//await expect(transaction).to.be.revertedWith("IncrementalQuinTreeTest: tree does not exist")
//})

//it("Should not update a leaf if the new value is the same as the old one", async () => {
//const leaf = BigInt(3)

//const transaction = contract.updateLeaf(treeId, leaf, leaf, [[0, 1, 2, 3]], [0])

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: new leaf cannot be the same as the old one")
//})

//it("Should not update a leaf if its new value is > SNARK_SCALAR_FIELD", async () => {
//const leaf = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495618")

//const transaction = contract.updateLeaf(treeId, BigInt(3), leaf, [[0, 1, 2, 3]], [0])

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: new leaf must be < SNARK_SCALAR_FIELD")
//})

//it("Should not update a leaf if its original value is > SNARK_SCALAR_FIELD", async () => {
//const leaf = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495618")

//const transaction = contract.updateLeaf(treeId, leaf, BigInt(4), [[0, 1, 2, 3]], [0])

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: leaf must be < SNARK_SCALAR_FIELD")
//})

//it("Should not update a leaf if the path indices are wrong", async () => {
//const treeId = ethers.utils.formatBytes32String("tree2")
//const tree = createTree(depth, 0, 5)

//for (let i = 0; i < 6; i += 1) {
//tree.insert(BigInt(i + 1))
//}

//const leaf = BigInt(1337)

//tree.update(2, leaf)

//const { pathIndices, siblings } = tree.createProof(2)

//pathIndices[3] = 6

//const transaction = contract.updateLeaf(treeId, BigInt(3), leaf, siblings, pathIndices)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: path index is not between 0 and 4")
//})

//it("Should not update a leaf if the wrong current leaf is given", async () => {
//const treeId = ethers.utils.formatBytes32String("tree2")
//const tree = createTree(depth, 0, 5)

//for (let i = 0; i < 6; i += 1) {
//tree.insert(BigInt(i + 1))
//}

//const leaf = BigInt(1337)

//tree.update(2, leaf)

//const { pathIndices, siblings } = tree.createProof(2)
//const transaction = contract.updateLeaf(treeId, BigInt(4), leaf, siblings, pathIndices)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: leaf is not part of the tree")
//})

//it("Should update a leaf", async () => {
//const treeId = ethers.utils.formatBytes32String("tree2")
//const tree = createTree(depth, 0, 5)

//for (let i = 0; i < 6; i += 1) {
//tree.insert(BigInt(i + 1))
//}

//const leaf = BigInt(1337)

//tree.update(2, leaf)

//const { pathIndices, siblings, root } = tree.createProof(2)
//const transaction = contract.updateLeaf(treeId, BigInt(3), leaf, siblings, pathIndices)

//await expect(transaction).to.emit(contract, "LeafUpdated").withArgs(treeId, leaf, root)
//})

//it("Should not remove a leaf if the tree does not exist", async () => {
//const treeId = ethers.utils.formatBytes32String("none")

//const transaction = contract.removeLeaf(treeId, leaf, [[0, 1, 2, 3]], [0])

//await expect(transaction).to.be.revertedWith("IncrementalQuinTreeTest: tree does not exist")
//})

//it("Should not remove a leaf if its value is > SNARK_SCALAR_FIELD", async () => {
//const leaf = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495618")

//const transaction = contract.removeLeaf(treeId, leaf, [[0, 1, 2, 3]], [0])

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: leaf must be < SNARK_SCALAR_FIELD")
//})

//it("Should remove a leaf", async () => {
//const treeId = ethers.utils.formatBytes32String("hello")
//const tree = createTree(depth, 3, 5)

//tree.delete(0)

//await contract.createTree(treeId, depth)
//await contract.insertLeaf(treeId, BigInt(1))
//await contract.insertLeaf(treeId, BigInt(2))
//await contract.insertLeaf(treeId, BigInt(3))

//const { siblings, pathIndices, root } = tree.createProof(0)
//const transaction = contract.removeLeaf(treeId, BigInt(1), siblings, pathIndices)

//await expect(transaction).to.emit(contract, "LeafRemoved").withArgs(treeId, BigInt(1), root)
//})

//it("Should remove another leaf", async () => {
//const treeId = ethers.utils.formatBytes32String("hello")
//const tree = createTree(depth, 3, 5)

//tree.delete(0)
//tree.delete(1)

//const { siblings, pathIndices, root } = tree.createProof(1)

//const transaction = contract.removeLeaf(treeId, BigInt(2), siblings, pathIndices)

//await expect(transaction).to.emit(contract, "LeafRemoved").withArgs(treeId, BigInt(2), root)
//})

//it("Should not update a leaf that hasn't been inserted yet", async () => {
//// deploy a new, empty tree
//const treeId = ethers.utils.formatBytes32String("brokenTree")
//contract.createTree(treeId, depth)
//const tree = createTree(depth, 0, 5)

//// insert 4 leaves into the tree
//for (let i = 0; i < 4; i += 1) {
//tree.insert(BigInt(i + 1))
//await contract.insertLeaf(treeId, BigInt(i + 1))
//}

//// we're going to try to update leaf 7, despite there only being 4 leaves in the tree
//const leaf = BigInt(42069)

//// note that we can insert zeros into the js library tree and the root won't change!
//// that's because we use the zeros optimization to calculate the roots efficiently.
//// technically speaking, there isn't an "empty" tree, there is only a tree that is
//// entirely full of the zero value at every index. therefore inserting the zero value
//// at any point into an incremental merkle tree doesn't change it's root, because
//// that is already the data the root was calculated from previously. in principle,
//// we can update any leaf that hasn't been inserted yet using this method
//const rootBeforeZeros = tree.root
//tree.insert(0)
//tree.insert(0)
//tree.insert(0)
//// the root doesn't change because the tree started full with 0s!
//expect(tree.root).to.be.equal(rootBeforeZeros)

//// now we can make a merkle proof of zero being included at the uninitialized index
//const { pathIndices, siblings } = tree.createProof(6)

//const transaction = contract.updateLeaf(treeId, BigInt(0), leaf, siblings, pathIndices)
//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: leaf index out of range")
//})

//it("Should not remove a leaf that does not exist", async () => {
//const treeId = ethers.utils.formatBytes32String("hello")
//const tree = createTree(depth, 3, 5)

//tree.delete(0)
//tree.delete(1)

//const { siblings, pathIndices } = tree.createProof(0)

//const transaction = contract.removeLeaf(treeId, BigInt(4), siblings, pathIndices)

//await expect(transaction).to.be.revertedWith("IncrementalQuinTree: leaf is not part of the tree")
//})

//it("Should insert a leaf in a tree after a removal", async () => {
//const treeId = ethers.utils.formatBytes32String("hello")
//const tree = createTree(depth, 4, 5)

//tree.delete(0)
//tree.delete(1)

//const transaction = contract.insertLeaf(treeId, BigInt(4))

//await expect(transaction).to.emit(contract, "LeafInserted").withArgs(treeId, BigInt(4), tree.root)
//})

//it("Should insert 4 leaves and remove them all", async () => {
//const treeId = ethers.utils.formatBytes32String("complex")
//const tree = createTree(depth, 4, 5)

//await contract.createTree(treeId, depth)

//for (let i = 0; i < 4; i += 1) {
//await contract.insertLeaf(treeId, BigInt(i + 1))
//}

//for (let i = 0; i < 4; i += 1) {
//tree.delete(i)

//const { siblings, pathIndices } = tree.createProof(i)

//await contract.removeLeaf(treeId, BigInt(i + 1), siblings, pathIndices)
//}

//const { root } = await contract.trees(treeId)

//expect(root).to.equal(tree.root)
//})
//})
Loading

0 comments on commit 97cf1e6

Please sign in to comment.