Skip to content

Commit

Permalink
Enable proof verification without full tree (#15)
Browse files Browse the repository at this point in the history
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Francisco Giordano <fg@frang.io>
  • Loading branch information
3 people authored Mar 15, 2023
1 parent 2ce6a45 commit 95e9ed3
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.0.3

- Added `StandardMerkleTree.verify` static method for verification of a proof for given root, leaf, and leaf encoding.

## 1.0.2

- Added `StandardMerkleTree` methods `verify` and `verifyMultiProof`.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ Creates a standard merkle tree out of an array of the elements in the tree, alon
> **Note**
> Consider reading the array of elements from a CSV file for easy interoperability with spreadsheets or other data processing pipelines.
### `StandardMerkleTree.verify`

```typescript
const verified = StandardMerkleTree.verify(root, ['address', 'uint'], [alice, '100'], proof);
```

Returns a boolean that is `true` when the proof verifies that the value is contained in the tree given only the proof, merkle root, and encoding.

### `tree.root`

```typescript
Expand Down
20 changes: 20 additions & 0 deletions src/standard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ describe('standard merkle tree', () => {
}
});

it('generates valid single proofs for all leaves from root and encoding', () => {
const { t } = characters('abcdef');

for (const [, leaf] of t.entries()) {
const proof = t.getProof(leaf);

assert(StandardMerkleTree.verify(t.root, ['string'], leaf, proof));
}
});

it('rejects invalid proof using static verify method', () => {
const { t } = characters('abcdef');
const { t: fakeTree } = characters('xyz');

const testLeaf = ['x'];
const proof = fakeTree.getProof(testLeaf);

assert(!StandardMerkleTree.verify(t.root, ['string'], testLeaf, proof));
});

it('generates valid multiproofs', () => {
const { t, l } = characters('abcdef');

Expand Down
7 changes: 6 additions & 1 deletion src/standard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class StandardMerkleTree<T extends any[]> {
private readonly values: { value: T, treeIndex: number }[],
private readonly leafEncoding: string[],
) {
this.hashLookup =
this.hashLookup =
Object.fromEntries(values.map(({ value }, valueIndex) => [
hex(standardLeafHash(value, leafEncoding)),
valueIndex,
Expand Down Expand Up @@ -61,6 +61,11 @@ export class StandardMerkleTree<T extends any[]> {
);
}

static verify<T extends any[]>(root: string, leafEncoding: string[], leaf: T, proof: string[]): boolean {
const impliedRoot = processProof(standardLeafHash(leaf, leafEncoding), proof.map(hexToBytes));
return equalsBytes(impliedRoot, hexToBytes(root));
}

dump(): StandardMerkleTreeData<T> {
return {
format: 'standard-v1',
Expand Down

0 comments on commit 95e9ed3

Please sign in to comment.