OpenZeppelin / merkle-tree

A JavaScript library to generate merkle trees and merkle proofs.
MIT License
453 stars 109 forks source link

Add verify functions #10

Closed frangio closed 1 year ago

frangio commented 1 year ago

Fixes #8

Amxx commented 1 year ago

getProof and getMultiProof automatically verify the proofs that they produced. IMO, this should be done using these new functions.

Otherwize looks good.

Amxx commented 1 year ago

For getProof the change is quite simple:

     // check proof
-    const hash = this.tree[treeIndex]!;
-    const impliedRoot = processProof(hash, proof);
-    if (!equalsBytes(impliedRoot, this.tree[0]!)) {
+    if (!this.verify(leaf, proof.map(bytesToHex))) {
       throw new Error('Unable to prove value');
     }

But for getMultiProof its quite more complex because we need the leaves in T format

     // check proof
-    const impliedRoot = processMultiProof(proof);
-    if (!equalsBytes(impliedRoot, this.tree[0]!)) {
+    if (!this.verifyMultiProof({
+      leaves: indices.map(i => this.values.find(e => e.treeIndex == i)!.value),
+      proof: proof.proof.map(bytesToHex),
+      proofFlags: proof.proofFlags,
+    })) {
       throw new Error('Unable to prove values');
     }
frangio commented 1 year ago

I implemented that suggestion but I refactored the code a little to avoid converting back and forth between string and Bytes.

frangio commented 1 year ago

Do you mean that maybe they shouldn't be private? Let's keep them private for now because they work on Bytes values and not on strings like the rest of the StandardMerkleTree interface.

Eventually I would be interested in making standard and core both work generically on both Bytes and strings.

Amxx commented 1 year ago

Do you mean that maybe they shouldn't be private?

I meant they should be private, which they are. My bad.

Amxx commented 1 year ago

Eventually I would be interested in making standard and core both work generically on both Bytes and strings.

I know we don't like dependencies, but IMO there is already a de-facto standard for that: https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L12

duktig666 commented 1 year ago

Can I directly call a similar method in JS and keep it consistent with solidity

solidity Provides such a method

function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
    return processProof(proof, leaf) == root;
}

https://github.com/merkletreejs/merkletreejs/blob/master/src/MerkleTree.ts 也实现了类似的方法:

verify (proof: any[], targetNode: Buffer | string, root: Buffer | string):boolean {

}
const tree = StandardMerkleTree.of();

Can Tree call verify directly?

duktig666 commented 1 year ago

tree. verify();