Skip to content

Commit bd77a74

Browse files
authored
mpt: simplify rangeProof handling & flatten mpt file structure (#3740)
1 parent cfc5309 commit bd77a74

File tree

17 files changed

+37
-74
lines changed

17 files changed

+37
-74
lines changed

packages/client/src/sync/fetcher/accountfetcher.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
setLengthLeft,
1818
} from '@ethereumjs/util'
1919
import debugDefault from 'debug'
20-
import { keccak256 } from 'ethereum-cryptography/keccak.js'
2120

2221
import { Event } from '../../types.js'
2322
import { short } from '../../util/index.js'
@@ -324,10 +323,15 @@ export class AccountFetcher extends Fetcher<JobTask, AccountData[], AccountData>
324323
const keys = accounts.map((acc: any) => acc.hash)
325324
const values = accounts.map((acc: any) => accountBodyToRLP(acc.body))
326325
// convert the request to the right values
327-
return verifyMerkleRangeProof(stateRoot, origin, keys[keys.length - 1], keys, values, proof, {
328-
common: this.config.chainCommon,
329-
useKeyHashingFunction: this.config.chainCommon?.customCrypto?.keccak256 ?? keccak256,
330-
})
326+
return verifyMerkleRangeProof(
327+
stateRoot,
328+
origin,
329+
keys[keys.length - 1],
330+
keys,
331+
values,
332+
proof,
333+
this.config.chainCommon?.customCrypto?.keccak256,
334+
)
331335
}
332336

333337
private getOrigin(job: Job<JobTask, AccountData[], AccountData>): Uint8Array {
@@ -412,7 +416,6 @@ export class AccountFetcher extends Fetcher<JobTask, AccountData[], AccountData>
412416
[],
413417
[],
414418
<any>rangeResult.proof,
415-
{ useKeyHashingFunction: keccak256 },
416419
)
417420
// if proof is false, reject corrupt peer
418421
if (isMissingRightRange !== false) return undefined

packages/client/src/sync/fetcher/storagefetcher.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
short,
1515
} from '@ethereumjs/util'
1616
import debugDefault from 'debug'
17-
import { keccak256 } from 'ethereum-cryptography/keccak'
1817

1918
import { Fetcher } from './fetcher.js'
2019
import { getInitFetcherDoneFlags } from './types.js'
@@ -135,10 +134,7 @@ export class StorageFetcher extends Fetcher<JobTask, StorageData[][], StorageDat
135134
keys,
136135
values,
137136
proof ?? null,
138-
{
139-
common: this.config.chainCommon,
140-
useKeyHashingFunction: this.config.chainCommon?.customCrypto?.keccak256 ?? keccak256,
141-
},
137+
this.config.chainCommon?.customCrypto?.keccak256,
142138
)
143139
} catch (err) {
144140
this.DEBUG && this.debug(`verifyRangeProof failure: ${(err as Error).stack}`)
@@ -287,7 +283,6 @@ export class StorageFetcher extends Fetcher<JobTask, StorageData[][], StorageDat
287283
[],
288284
[],
289285
<any>rangeResult.proof,
290-
{ useKeyHashingFunction: keccak256 },
291286
)
292287

293288
// if proof is false, reject corrupt peer
@@ -344,10 +339,7 @@ export class StorageFetcher extends Fetcher<JobTask, StorageData[][], StorageDat
344339
accountSlots.map((s) => s.hash),
345340
accountSlots.map((s) => s.body),
346341
null,
347-
{
348-
common: this.config.chainCommon,
349-
useKeyHashingFunction: this.config.chainCommon?.customCrypto?.keccak256 ?? keccak256,
350-
},
342+
this.config.chainCommon?.customCrypto?.keccak256,
351343
)
352344

353345
if (proof?.length === 0)

packages/client/test/net/protocol/snapprotocol.spec.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,7 @@ describe('[SnapProtocol]', () => {
191191
try {
192192
const keys = accounts.map((acc: any) => acc.hash)
193193
const values = accounts.map((acc: any) => accountBodyToRLP(acc.body))
194-
await verifyMerkleRangeProof(stateRoot, keys[0], keys[keys.length - 1], keys, values, proof, {
195-
useKeyHashingFunction: keccak256,
196-
})
194+
await verifyMerkleRangeProof(stateRoot, keys[0], keys[keys.length - 1], keys, values, proof)
197195
} catch (e) {
198196
assert.fail(`AccountRange proof verification failed with message=${(e as Error).message}`)
199197
}
@@ -331,9 +329,6 @@ describe('[SnapProtocol]', () => {
331329
keys,
332330
values,
333331
proof,
334-
{
335-
useKeyHashingFunction: keccak256,
336-
},
337332
)
338333
} catch (e) {
339334
assert.fail(`StorageRange proof verification failed with message=${(e as Error).message}`)

packages/mpt/src/db/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './checkpoint.js'
1+
export * from './checkpointDB.js'

packages/mpt/src/mpt.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
import debug from 'debug'
2020
import { keccak256 } from 'ethereum-cryptography/keccak.js'
2121

22-
import { CheckpointDB } from './db/index.js'
22+
import { CheckpointDB } from './db/checkpointDB.js'
2323
import {
2424
BranchMPTNode,
2525
ExtensionMPTNode,

packages/mpt/src/proof/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './proof.js'
2+
export * from './range.js'

packages/mpt/src/proof/proof.ts

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import { bytesToHex, concatBytes, equalsBytes } from '@ethereumjs/util'
2-
import { keccak256 } from 'ethereum-cryptography/keccak'
32

43
import { createMPTFromProof } from '../constructors.js'
54
import { MerklePatriciaTrie } from '../index.js'
6-
import { bytesToNibbles } from '../util/nibbles.js'
7-
8-
import { verifyRangeProof } from './range.js'
95

106
import type { MPTOpts, Proof } from '../index.js'
117
import type { PutBatch } from '@ethereumjs/util'
@@ -34,39 +30,6 @@ export async function verifyMerkleProof(
3430
}
3531
}
3632

37-
// /**
38-
// * A range proof is a proof that includes the encoded trie nodes from the root node to leaf node for one or more branches of a trie,
39-
// * allowing an entire range of leaf nodes to be validated. This is useful in applications such as snap sync where contiguous ranges
40-
// * of state trie data is received and validated for constructing world state, locally. Also see {@link verifyRangeProof}.
41-
// * @param rootHash - root hash of state trie this proof is being verified against.
42-
// * @param firstKey - first key of range being proven.
43-
// * @param lastKey - last key of range being proven.
44-
// * @param keys - key list of leaf data being proven.
45-
// * @param values - value list of leaf data being proven, one-to-one correspondence with keys.
46-
// * @param proof - proof node list, if all-elements-proof where no proof is needed, proof should be null, and both `firstKey` and `lastKey` must be null as well
47-
// * @param opts - optional, the opts may include a custom hashing function to use with the trie for proof verification
48-
// * @returns a flag to indicate whether there exists more trie node in the trie
49-
// */
50-
export function verifyMerkleRangeProof(
51-
rootHash: Uint8Array,
52-
firstKey: Uint8Array | null,
53-
lastKey: Uint8Array | null,
54-
keys: Uint8Array[],
55-
values: Uint8Array[],
56-
proof: Uint8Array[] | null,
57-
opts?: MPTOpts,
58-
): Promise<boolean> {
59-
return verifyRangeProof(
60-
rootHash,
61-
firstKey && bytesToNibbles(firstKey),
62-
lastKey && bytesToNibbles(lastKey),
63-
keys.map((k) => k).map(bytesToNibbles),
64-
values,
65-
proof,
66-
opts?.useKeyHashingFunction ?? keccak256,
67-
)
68-
}
69-
7033
/**
7134
* Creates a proof from a trie and key that can be verified using {@link verifyMPTWithMerkleProof}. An (EIP-1186)[https://eips.ethereum.org/EIPS/eip-1186] proof contains
7235
* the encoded trie nodes from the root node to the leaf node storing state data. The returned proof will be in the format of an array that contains Uint8Arrays of

packages/mpt/src/proof/range.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { equalsBytes } from '@ethereumjs/util'
2+
import { keccak256 } from 'ethereum-cryptography/keccak'
23

34
import { createMPTFromProof } from '../index.js'
45
import { MerklePatriciaTrie } from '../mpt.js'
56
import { BranchMPTNode, ExtensionMPTNode, LeafMPTNode } from '../node/index.js'
6-
import { nibblesCompare, nibblesTypeToPackedBytes } from '../util/nibbles.js'
7+
import { bytesToNibbles, nibblesCompare, nibblesTypeToPackedBytes } from '../util/nibbles.js'
78

89
import type { HashKeysFunction, MPTNode, Nibbles } from '../types.js'
910

@@ -386,9 +387,11 @@ async function hasRightElement(trie: MerklePatriciaTrie, key: Nibbles): Promise<
386387
}
387388

388389
/**
389-
* verifyRangeProof checks whether the given leaf nodes and edge proof
390-
* can prove the given trie leaves range is matched with the specific root.
391-
* Used internally by the verifyMerkleRangeProof wrapper function.
390+
* Checks whether the given leaf nodes and edge proof can prove the given trie leaves range is matched with the specific root.
391+
*
392+
* A range proof is a proof that includes the encoded trie nodes from the root node to leaf node for one or more branches of a trie,
393+
* allowing an entire range of leaf nodes to be validated. This is useful in applications such as snap sync where contiguous ranges
394+
* of state trie data is received and validated for constructing world state, locally.
392395
*
393396
* There are four situations:
394397
*
@@ -412,17 +415,23 @@ async function hasRightElement(trie: MerklePatriciaTrie, key: Nibbles): Promise<
412415
* @param keys - key list of leaf data being proven.
413416
* @param values - value list of leaf data being proven, one-to-one correspondence with keys.
414417
* @param proof - proof node list, if all-elements-proof where no proof is needed, proof should be null, and both `firstKey` and `lastKey` must be null as well
418+
* @param opts - optional, the opts may include a custom hashing function to use with the trie for proof verification
415419
* @returns a flag to indicate whether there exists more trie node in the trie
416420
*/
417-
export async function verifyRangeProof(
421+
export async function verifyMerkleRangeProof(
418422
rootHash: Uint8Array,
419-
firstKey: Nibbles | null,
420-
lastKey: Nibbles | null,
421-
keys: Nibbles[],
423+
firstKeyRaw: Uint8Array | null,
424+
lastKeyRaw: Uint8Array | null,
425+
keysRaw: Uint8Array[],
422426
values: Uint8Array[],
423427
proof: Uint8Array[] | null,
424-
useKeyHashingFunction: HashKeysFunction,
428+
useKeyHashingFunction: HashKeysFunction = keccak256,
425429
): Promise<boolean> {
430+
// Convert Uint8Array keys to nibbles
431+
const firstKey = firstKeyRaw !== null ? bytesToNibbles(firstKeyRaw) : null
432+
const lastKey = lastKeyRaw !== null ? bytesToNibbles(lastKeyRaw) : null
433+
const keys = keysRaw.map(bytesToNibbles)
434+
426435
if (keys.length !== values.length) {
427436
throw new Error('invalid keys length or values length')
428437
}

packages/statemanager/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export * from './cache/index.js'
22
export * from './merkleStateManager.js'
3-
export * from './proofs/index.js'
3+
export * from './proof/index.js'
44
export * from './rpcStateManager.js'
55
export * from './simpleStateManager.js'
66
export * from './statefulVerkleStateManager.js'

0 commit comments

Comments
 (0)