Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
replace ethers 5.7 dependency with @metamask/utils and ethereum-crypt…
Browse files Browse the repository at this point in the history
…ography
Amxx committed Oct 9, 2024
1 parent 31c37cf commit a239036
Showing 9 changed files with 338 additions and 433 deletions.
714 changes: 304 additions & 410 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -26,10 +26,9 @@
"author": "Francisco Giordano <fg@frang.io>",
"license": "MIT",
"dependencies": {
"@ethersproject/abi": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0"
"@metamask/abi-utils": "^2.0.4",
"@metamask/utils": "^9.3.0",
"ethereum-cryptography": "^3.0.0"
},
"devDependencies": {
"@fast-check/ava": "^1.2.1",
10 changes: 7 additions & 3 deletions src/bytes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { BytesLike } from '@ethersproject/bytes';
type HexString = string;
import type { BytesLike } from '@metamask/utils';
type HexString = `0x${string}`;

import { arrayify as toBytes, hexlify as toHex, concat } from '@ethersproject/bytes';
import {

Check warning on line 4 in src/bytes.ts

GitHub Actions / test

Replace `⏎··createBytes·as·toBytes,⏎··createHex·as·toHex,⏎··concatBytes·as·concat,⏎` with `·createBytes·as·toBytes,·createHex·as·toHex,·concatBytes·as·concat·`
createBytes as toBytes,
createHex as toHex,
concatBytes as concat,
} from '@metamask/utils';

function compare(a: BytesLike, b: BytesLike): number {
const diff = BigInt(toHex(a)) - BigInt(toHex(b));
5 changes: 3 additions & 2 deletions src/core.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { test, testProp, fc } from '@fast-check/ava';
import { HashZero as zero } from '@ethersproject/constants';
import {
makeMerkleTree,
getProof,
@@ -9,9 +8,11 @@ import {
isValidMerkleTree,
renderMerkleTree,
} from './core';
import { toHex } from './bytes';
import { HexString, toHex } from './bytes';
import { InvalidArgumentError, InvariantError } from './utils/errors';

const zero: HexString = '0x0000000000000000000000000000000000000000000000000000000000000000';

const leaf = fc.uint8Array({ minLength: 32, maxLength: 32 });
const leaves = fc.array(leaf, { minLength: 1 });
const leavesAndIndex = leaves.chain(xs => fc.tuple(fc.constant(xs), fc.nat({ max: xs.length - 1 })));
6 changes: 3 additions & 3 deletions src/core.ts
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ export function makeMerkleTree(leaves: BytesLike[], nodeHash: NodeHash = standar
export function getProof(tree: BytesLike[], index: number): HexString[] {
checkLeafNode(tree, index);

const proof = [];
const proof: HexString[] = [];
while (index > 0) {
proof.push(toHex(tree[siblingIndex(index)]!));
index = parentIndex(index);
@@ -67,7 +67,7 @@ export function getMultiProof(tree: BytesLike[], indices: number[]): MultiProof<
);

const stack = Array.from(indices); // copy
const proof = [];
const proof: HexString[] = [];
const proofFlags = [];

while (stack.length > 0 && stack[0]! > 0) {
@@ -145,7 +145,7 @@ export function isValidMerkleTree(tree: BytesLike[], nodeHash: NodeHash = standa
return tree.length > 0;
}

export function renderMerkleTree(tree: BytesLike[]): HexString {
export function renderMerkleTree(tree: BytesLike[]): string {
validateArgument(tree.length !== 0, 'Expected non-zero number of nodes');

const stack: [number, number[]][] = [[0, []]];
12 changes: 8 additions & 4 deletions src/hashes.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { defaultAbiCoder } from '@ethersproject/abi';
import { keccak256 } from '@ethersproject/keccak256';
import { BytesLike, HexString, concat, compare } from './bytes';
import { encode } from '@metamask/abi-utils';
import { keccak256 as _keccak256 } from "ethereum-cryptography/keccak.js";

Check warning on line 2 in src/hashes.ts

GitHub Actions / test

Replace `"ethereum-cryptography/keccak.js"` with `'ethereum-cryptography/keccak.js'`
import { BytesLike, HexString, toHex, toBytes, concat, compare } from './bytes';

export type LeafHash<T> = (leaf: T) => HexString;
export type NodeHash = (left: BytesLike, right: BytesLike) => HexString;

Check warning on line 6 in src/hashes.ts

GitHub Actions / test

Delete `⏎`


export function keccak256(input: BytesLike): HexString {
return toHex(_keccak256(toBytes(input)));
}
export function standardLeafHash<T extends any[]>(types: string[], value: T): HexString {
return keccak256(keccak256(defaultAbiCoder.encode(types, value)));
return keccak256(keccak256(encode(types, value)));
}

export function standardNodeHash(a: BytesLike, b: BytesLike): HexString {
7 changes: 4 additions & 3 deletions src/simple.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { test, testProp, fc } from '@fast-check/ava';
import { HashZero as zero } from '@ethersproject/constants';
import { keccak256 } from '@ethersproject/keccak256';
import { SimpleMerkleTree } from './simple';
import { BytesLike, HexString, concat, compare, toHex } from './bytes';
import { keccak256 } from './hashes';
import { InvalidArgumentError, InvariantError } from './utils/errors';

const zero: HexString = '0x0000000000000000000000000000000000000000000000000000000000000000';

fc.configureGlobal({ numRuns: process.env.CI ? 5000 : 100 });

const reverseNodeHash = (a: BytesLike, b: BytesLike): HexString => keccak256(concat([a, b].sort(compare).reverse()));
@@ -149,7 +150,7 @@ testProp('reject loading dump with wrong node hash', [fc.array(leaf, { minLength
test('reject invalid leaf size', t => {
const invalidLeaf = '0x000000000000000000000000000000000000000000000000000000000000000000';
t.throws(() => SimpleMerkleTree.of([invalidLeaf]), {
message: `incorrect data length (argument=null, value="${invalidLeaf}", code=INVALID_ARGUMENT, version=abi/5.7.0)`,
message: 'Unable to encode value: Expected a value of length 32, but received a value of length 33.',
});
});

4 changes: 2 additions & 2 deletions src/simple.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defaultAbiCoder } from '@ethersproject/abi';
import { encode } from '@metamask/abi-utils';
import { BytesLike, HexString, toHex } from './bytes';
import { MultiProof, processProof, processMultiProof } from './core';
import { MerkleTreeData, MerkleTreeImpl } from './merkletree';
@@ -16,7 +16,7 @@ export interface SimpleMerkleTreeOptions extends MerkleTreeOptions {
}

export function formatLeaf(value: BytesLike): HexString {
return defaultAbiCoder.encode(['bytes32'], [value]);
return toHex(encode(['bytes32'], [value]));
}

export class SimpleMerkleTree extends MerkleTreeImpl<BytesLike> {
6 changes: 4 additions & 2 deletions src/standard.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { test, testProp, fc } from '@fast-check/ava';
import { HashZero as zero } from '@ethersproject/constants';
import { keccak256 } from '@ethersproject/keccak256';
import { StandardMerkleTree } from './standard';
import { HexString } from './bytes';
import { keccak256 } from './hashes';
import { InvalidArgumentError, InvariantError } from './utils/errors';

const zero: HexString = '0x0000000000000000000000000000000000000000000000000000000000000000';

fc.configureGlobal({ numRuns: process.env.CI ? 5000 : 100 });

const leafEncoding = ['uint256', 'string[]'];

0 comments on commit a239036

Please sign in to comment.