@feelyourprotocol/mpt 8141.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +448 -0
- package/dist/cjs/constructors.d.ts +12 -0
- package/dist/cjs/constructors.d.ts.map +1 -0
- package/dist/cjs/constructors.js +57 -0
- package/dist/cjs/constructors.js.map +1 -0
- package/dist/cjs/db/checkpointDB.d.ts +87 -0
- package/dist/cjs/db/checkpointDB.d.ts.map +1 -0
- package/dist/cjs/db/checkpointDB.js +258 -0
- package/dist/cjs/db/checkpointDB.js.map +1 -0
- package/dist/cjs/db/index.d.ts +2 -0
- package/dist/cjs/db/index.d.ts.map +1 -0
- package/dist/cjs/db/index.js +18 -0
- package/dist/cjs/db/index.js.map +1 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +24 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/mpt.d.ts +261 -0
- package/dist/cjs/mpt.d.ts.map +1 -0
- package/dist/cjs/mpt.js +900 -0
- package/dist/cjs/mpt.js.map +1 -0
- package/dist/cjs/node/branch.d.ts +14 -0
- package/dist/cjs/node/branch.d.ts.map +1 -0
- package/dist/cjs/node/branch.js +52 -0
- package/dist/cjs/node/branch.js.map +1 -0
- package/dist/cjs/node/extension.d.ts +7 -0
- package/dist/cjs/node/extension.d.ts.map +1 -0
- package/dist/cjs/node/extension.js +14 -0
- package/dist/cjs/node/extension.js.map +1 -0
- package/dist/cjs/node/extensionOrLeafNodeBase.d.ts +15 -0
- package/dist/cjs/node/extensionOrLeafNodeBase.d.ts.map +1 -0
- package/dist/cjs/node/extensionOrLeafNodeBase.js +42 -0
- package/dist/cjs/node/extensionOrLeafNodeBase.js.map +1 -0
- package/dist/cjs/node/index.d.ts +5 -0
- package/dist/cjs/node/index.d.ts.map +1 -0
- package/dist/cjs/node/index.js +21 -0
- package/dist/cjs/node/index.js.map +1 -0
- package/dist/cjs/node/leaf.d.ts +7 -0
- package/dist/cjs/node/leaf.d.ts.map +1 -0
- package/dist/cjs/node/leaf.js +14 -0
- package/dist/cjs/node/leaf.js.map +1 -0
- package/dist/cjs/node/util.d.ts +8 -0
- package/dist/cjs/node/util.d.ts.map +1 -0
- package/dist/cjs/node/util.js +38 -0
- package/dist/cjs/node/util.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/proof/index.d.ts +3 -0
- package/dist/cjs/proof/index.d.ts.map +1 -0
- package/dist/cjs/proof/index.js +19 -0
- package/dist/cjs/proof/index.js.map +1 -0
- package/dist/cjs/proof/proof.d.ts +41 -0
- package/dist/cjs/proof/proof.d.ts.map +1 -0
- package/dist/cjs/proof/proof.js +119 -0
- package/dist/cjs/proof/proof.js.map +1 -0
- package/dist/cjs/proof/range.d.ts +35 -0
- package/dist/cjs/proof/range.d.ts.map +1 -0
- package/dist/cjs/proof/range.js +456 -0
- package/dist/cjs/proof/range.js.map +1 -0
- package/dist/cjs/types.d.ts +110 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/util/asyncWalk.d.ts +20 -0
- package/dist/cjs/util/asyncWalk.d.ts.map +1 -0
- package/dist/cjs/util/asyncWalk.js +50 -0
- package/dist/cjs/util/asyncWalk.js.map +1 -0
- package/dist/cjs/util/encoding.d.ts +31 -0
- package/dist/cjs/util/encoding.d.ts.map +1 -0
- package/dist/cjs/util/encoding.js +200 -0
- package/dist/cjs/util/encoding.js.map +1 -0
- package/dist/cjs/util/genesisState.d.ts +6 -0
- package/dist/cjs/util/genesisState.d.ts.map +1 -0
- package/dist/cjs/util/genesisState.js +45 -0
- package/dist/cjs/util/genesisState.js.map +1 -0
- package/dist/cjs/util/hex.d.ts +20 -0
- package/dist/cjs/util/hex.d.ts.map +1 -0
- package/dist/cjs/util/hex.js +48 -0
- package/dist/cjs/util/hex.js.map +1 -0
- package/dist/cjs/util/index.d.ts +4 -0
- package/dist/cjs/util/index.d.ts.map +1 -0
- package/dist/cjs/util/index.js +20 -0
- package/dist/cjs/util/index.js.map +1 -0
- package/dist/cjs/util/nibbles.d.ts +30 -0
- package/dist/cjs/util/nibbles.d.ts.map +1 -0
- package/dist/cjs/util/nibbles.js +79 -0
- package/dist/cjs/util/nibbles.js.map +1 -0
- package/dist/cjs/util/walkController.d.ts +72 -0
- package/dist/cjs/util/walkController.d.ts.map +1 -0
- package/dist/cjs/util/walkController.js +138 -0
- package/dist/cjs/util/walkController.js.map +1 -0
- package/dist/esm/constructors.d.ts +12 -0
- package/dist/esm/constructors.d.ts.map +1 -0
- package/dist/esm/constructors.js +53 -0
- package/dist/esm/constructors.js.map +1 -0
- package/dist/esm/db/checkpointDB.d.ts +87 -0
- package/dist/esm/db/checkpointDB.d.ts.map +1 -0
- package/dist/esm/db/checkpointDB.js +254 -0
- package/dist/esm/db/checkpointDB.js.map +1 -0
- package/dist/esm/db/index.d.ts +2 -0
- package/dist/esm/db/index.d.ts.map +1 -0
- package/dist/esm/db/index.js +2 -0
- package/dist/esm/db/index.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mpt.d.ts +261 -0
- package/dist/esm/mpt.d.ts.map +1 -0
- package/dist/esm/mpt.js +897 -0
- package/dist/esm/mpt.js.map +1 -0
- package/dist/esm/node/branch.d.ts +14 -0
- package/dist/esm/node/branch.d.ts.map +1 -0
- package/dist/esm/node/branch.js +48 -0
- package/dist/esm/node/branch.js.map +1 -0
- package/dist/esm/node/extension.d.ts +7 -0
- package/dist/esm/node/extension.d.ts.map +1 -0
- package/dist/esm/node/extension.js +10 -0
- package/dist/esm/node/extension.js.map +1 -0
- package/dist/esm/node/extensionOrLeafNodeBase.d.ts +15 -0
- package/dist/esm/node/extensionOrLeafNodeBase.d.ts.map +1 -0
- package/dist/esm/node/extensionOrLeafNodeBase.js +38 -0
- package/dist/esm/node/extensionOrLeafNodeBase.js.map +1 -0
- package/dist/esm/node/index.d.ts +5 -0
- package/dist/esm/node/index.d.ts.map +1 -0
- package/dist/esm/node/index.js +5 -0
- package/dist/esm/node/index.js.map +1 -0
- package/dist/esm/node/leaf.d.ts +7 -0
- package/dist/esm/node/leaf.d.ts.map +1 -0
- package/dist/esm/node/leaf.js +10 -0
- package/dist/esm/node/leaf.js.map +1 -0
- package/dist/esm/node/util.d.ts +8 -0
- package/dist/esm/node/util.d.ts.map +1 -0
- package/dist/esm/node/util.js +33 -0
- package/dist/esm/node/util.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/proof/index.d.ts +3 -0
- package/dist/esm/proof/index.d.ts.map +1 -0
- package/dist/esm/proof/index.js +3 -0
- package/dist/esm/proof/index.js.map +1 -0
- package/dist/esm/proof/proof.d.ts +41 -0
- package/dist/esm/proof/proof.d.ts.map +1 -0
- package/dist/esm/proof/proof.js +113 -0
- package/dist/esm/proof/proof.js.map +1 -0
- package/dist/esm/proof/range.d.ts +35 -0
- package/dist/esm/proof/range.d.ts.map +1 -0
- package/dist/esm/proof/range.js +453 -0
- package/dist/esm/proof/range.js.map +1 -0
- package/dist/esm/types.d.ts +110 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +3 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/util/asyncWalk.d.ts +20 -0
- package/dist/esm/util/asyncWalk.d.ts.map +1 -0
- package/dist/esm/util/asyncWalk.js +47 -0
- package/dist/esm/util/asyncWalk.js.map +1 -0
- package/dist/esm/util/encoding.d.ts +31 -0
- package/dist/esm/util/encoding.d.ts.map +1 -0
- package/dist/esm/util/encoding.js +188 -0
- package/dist/esm/util/encoding.js.map +1 -0
- package/dist/esm/util/genesisState.d.ts +6 -0
- package/dist/esm/util/genesisState.d.ts.map +1 -0
- package/dist/esm/util/genesisState.js +42 -0
- package/dist/esm/util/genesisState.js.map +1 -0
- package/dist/esm/util/hex.d.ts +20 -0
- package/dist/esm/util/hex.d.ts.map +1 -0
- package/dist/esm/util/hex.js +43 -0
- package/dist/esm/util/hex.js.map +1 -0
- package/dist/esm/util/index.d.ts +4 -0
- package/dist/esm/util/index.d.ts.map +1 -0
- package/dist/esm/util/index.js +4 -0
- package/dist/esm/util/index.js.map +1 -0
- package/dist/esm/util/nibbles.d.ts +30 -0
- package/dist/esm/util/nibbles.d.ts.map +1 -0
- package/dist/esm/util/nibbles.js +73 -0
- package/dist/esm/util/nibbles.js.map +1 -0
- package/dist/esm/util/walkController.d.ts +72 -0
- package/dist/esm/util/walkController.d.ts.map +1 -0
- package/dist/esm/util/walkController.js +134 -0
- package/dist/esm/util/walkController.js.map +1 -0
- package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
- package/package.json +85 -0
- package/src/constructors.ts +71 -0
- package/src/db/checkpointDB.ts +298 -0
- package/src/db/index.ts +1 -0
- package/src/index.ts +7 -0
- package/src/mpt.ts +1090 -0
- package/src/node/branch.ts +60 -0
- package/src/node/extension.ts +13 -0
- package/src/node/extensionOrLeafNodeBase.ts +54 -0
- package/src/node/index.ts +4 -0
- package/src/node/leaf.ts +13 -0
- package/src/node/util.ts +35 -0
- package/src/proof/index.ts +2 -0
- package/src/proof/proof.ts +135 -0
- package/src/proof/range.ts +542 -0
- package/src/types.ts +151 -0
- package/src/util/asyncWalk.ts +60 -0
- package/src/util/encoding.ts +209 -0
- package/src/util/genesisState.ts +52 -0
- package/src/util/hex.ts +47 -0
- package/src/util/index.ts +3 -0
- package/src/util/nibbles.ts +80 -0
- package/src/util/walkController.ts +172 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { RLP } from '@feelyourprotocol/rlp'
|
|
2
|
+
|
|
3
|
+
import type { BranchMPTNodeBranchValue, NodeReferenceOrRawMPTNode } from '../types.ts'
|
|
4
|
+
|
|
5
|
+
export class BranchMPTNode {
|
|
6
|
+
_branches: BranchMPTNodeBranchValue[]
|
|
7
|
+
_value: Uint8Array | null
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this._branches = new Array(16).fill(null)
|
|
11
|
+
this._value = null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static fromArray(arr: Uint8Array[]): BranchMPTNode {
|
|
15
|
+
const node = new BranchMPTNode()
|
|
16
|
+
node._branches = arr.slice(0, 16)
|
|
17
|
+
node._value = arr[16]
|
|
18
|
+
return node
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
value(v?: Uint8Array | null): Uint8Array | null {
|
|
22
|
+
if (v !== null && v !== undefined) {
|
|
23
|
+
this._value = v
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return this._value && this._value.length > 0 ? this._value : null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setBranch(i: number, v: BranchMPTNodeBranchValue) {
|
|
30
|
+
this._branches[i] = v
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
raw(): BranchMPTNodeBranchValue[] {
|
|
34
|
+
return [...this._branches, this._value]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
serialize(): Uint8Array {
|
|
38
|
+
return RLP.encode(this.raw())
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getBranch(i: number): BranchMPTNodeBranchValue {
|
|
42
|
+
const b = this._branches[i]
|
|
43
|
+
if (b !== null && b.length > 0) {
|
|
44
|
+
return b
|
|
45
|
+
} else {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getChildren(): [number, NodeReferenceOrRawMPTNode][] {
|
|
51
|
+
const children: [number, NodeReferenceOrRawMPTNode][] = []
|
|
52
|
+
for (let i = 0; i < 16; i++) {
|
|
53
|
+
const b = this._branches[i]
|
|
54
|
+
if (b !== null && b.length > 0) {
|
|
55
|
+
children.push([i, b])
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return children
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ExtensionOrLeafMPTNodeBase } from './extensionOrLeafNodeBase.ts'
|
|
2
|
+
|
|
3
|
+
import type { Nibbles, RawExtensionMPTNode } from '../types.ts'
|
|
4
|
+
|
|
5
|
+
export class ExtensionMPTNode extends ExtensionOrLeafMPTNodeBase {
|
|
6
|
+
constructor(nibbles: Nibbles, value: Uint8Array) {
|
|
7
|
+
super(nibbles, value, false)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
raw(): RawExtensionMPTNode {
|
|
11
|
+
return super.raw()
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { RLP } from '@feelyourprotocol/rlp'
|
|
2
|
+
|
|
3
|
+
import { addHexPrefix, removeHexPrefix } from '../util/hex.ts'
|
|
4
|
+
import { nibblesTypeToPackedBytes } from '../util/nibbles.ts'
|
|
5
|
+
|
|
6
|
+
import type { Nibbles, RawExtensionMPTNode, RawLeafMPTNode } from '../types.ts'
|
|
7
|
+
|
|
8
|
+
export abstract class ExtensionOrLeafMPTNodeBase {
|
|
9
|
+
_nibbles: Nibbles
|
|
10
|
+
_value: Uint8Array
|
|
11
|
+
_isLeaf: boolean
|
|
12
|
+
|
|
13
|
+
constructor(nibbles: Nibbles, value: Uint8Array, isLeaf: boolean) {
|
|
14
|
+
this._nibbles = nibbles
|
|
15
|
+
this._value = value
|
|
16
|
+
this._isLeaf = isLeaf
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static decodeKey(key: Nibbles): Nibbles {
|
|
20
|
+
return removeHexPrefix(key)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
encodedKey(): Nibbles {
|
|
24
|
+
return addHexPrefix(this._nibbles.slice(0), this._isLeaf)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
key(k?: Nibbles): Nibbles {
|
|
28
|
+
if (k !== undefined) {
|
|
29
|
+
this._nibbles = k
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return this._nibbles.slice(0)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
keyLength() {
|
|
36
|
+
return this._nibbles.length
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
value(v?: Uint8Array) {
|
|
40
|
+
if (v !== undefined) {
|
|
41
|
+
this._value = v
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return this._value
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
raw(): RawExtensionMPTNode | RawLeafMPTNode {
|
|
48
|
+
return [nibblesTypeToPackedBytes(this.encodedKey()), this._value]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
serialize(): Uint8Array {
|
|
52
|
+
return RLP.encode(this.raw())
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/node/leaf.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ExtensionOrLeafMPTNodeBase } from './extensionOrLeafNodeBase.ts'
|
|
2
|
+
|
|
3
|
+
import type { Nibbles, RawLeafMPTNode } from '../types.ts'
|
|
4
|
+
|
|
5
|
+
export class LeafMPTNode extends ExtensionOrLeafMPTNodeBase {
|
|
6
|
+
constructor(nibbles: Nibbles, value: Uint8Array) {
|
|
7
|
+
super(nibbles, value, true)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
raw(): RawLeafMPTNode {
|
|
11
|
+
return super.raw()
|
|
12
|
+
}
|
|
13
|
+
}
|
package/src/node/util.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RLP } from '@feelyourprotocol/rlp'
|
|
2
|
+
import { EthereumJSErrorWithoutCode, type NestedUint8Array } from '@feelyourprotocol/util'
|
|
3
|
+
|
|
4
|
+
import { isTerminator } from '../util/hex.ts'
|
|
5
|
+
import { bytesToNibbles } from '../util/nibbles.ts'
|
|
6
|
+
|
|
7
|
+
import { BranchMPTNode } from './branch.ts'
|
|
8
|
+
import { ExtensionMPTNode } from './extension.ts'
|
|
9
|
+
import { LeafMPTNode } from './leaf.ts'
|
|
10
|
+
|
|
11
|
+
export function decodeRawMPTNode(raw: Uint8Array[]) {
|
|
12
|
+
if (raw.length === 17) {
|
|
13
|
+
return BranchMPTNode.fromArray(raw)
|
|
14
|
+
} else if (raw.length === 2) {
|
|
15
|
+
const nibbles = bytesToNibbles(raw[0])
|
|
16
|
+
if (isTerminator(nibbles)) {
|
|
17
|
+
return new LeafMPTNode(LeafMPTNode.decodeKey(nibbles), raw[1])
|
|
18
|
+
}
|
|
19
|
+
return new ExtensionMPTNode(ExtensionMPTNode.decodeKey(nibbles), raw[1])
|
|
20
|
+
} else {
|
|
21
|
+
throw EthereumJSErrorWithoutCode('Invalid node')
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isRawMPTNode(n: Uint8Array | NestedUint8Array): n is Uint8Array[] {
|
|
26
|
+
return Array.isArray(n) && !(n instanceof Uint8Array)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function decodeMPTNode(node: Uint8Array) {
|
|
30
|
+
const decodedNode = RLP.decode(Uint8Array.from(node))
|
|
31
|
+
if (!isRawMPTNode(decodedNode)) {
|
|
32
|
+
throw EthereumJSErrorWithoutCode('Invalid node')
|
|
33
|
+
}
|
|
34
|
+
return decodeRawMPTNode(decodedNode)
|
|
35
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { EthereumJSErrorWithoutCode, bytesToHex, concatBytes, equalsBytes } from '@feelyourprotocol/util'
|
|
2
|
+
|
|
3
|
+
import { type MPTOpts, MerklePatriciaTrie, type Proof, createMPTFromProof } from '../index.ts'
|
|
4
|
+
|
|
5
|
+
import type { PutBatch } from '@feelyourprotocol/util'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* An (EIP-1186)[https://eips.ethereum.org/EIPS/eip-1186] proof contains the encoded trie nodes
|
|
9
|
+
* from the root node to the leaf node storing state data.
|
|
10
|
+
* @param rootHash Root hash of the trie that this proof was created from and is being verified for
|
|
11
|
+
* @param key Key that is being verified and that the proof is created for
|
|
12
|
+
* @param proof An (EIP-1186)[https://eips.ethereum.org/EIPS/eip-1186] proof contains the encoded trie nodes from the root node to the leaf node storing state data.
|
|
13
|
+
* @param opts optional, the opts may include a custom hashing function to use with the trie for proof verification
|
|
14
|
+
* @throws If proof is found to be invalid.
|
|
15
|
+
* @returns The value from the key, or null if valid proof of non-existence.
|
|
16
|
+
*/
|
|
17
|
+
export async function verifyMerkleProof(
|
|
18
|
+
key: Uint8Array,
|
|
19
|
+
proof: Proof,
|
|
20
|
+
opts?: MPTOpts,
|
|
21
|
+
): Promise<Uint8Array | null> {
|
|
22
|
+
try {
|
|
23
|
+
const proofTrie = await createMPTFromProof(proof, opts)
|
|
24
|
+
const value = await proofTrie.get(key, true)
|
|
25
|
+
return value
|
|
26
|
+
} catch {
|
|
27
|
+
throw EthereumJSErrorWithoutCode('Invalid proof provided')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 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
|
|
33
|
+
* 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
|
|
34
|
+
* serialized branch, extension, and/or leaf nodes.
|
|
35
|
+
* @param key key to create a proof for
|
|
36
|
+
*/
|
|
37
|
+
export async function createMerkleProof(trie: MerklePatriciaTrie, key: Uint8Array): Promise<Proof> {
|
|
38
|
+
trie['DEBUG'] && trie['debug'](`Creating Proof for Key: ${bytesToHex(key)}`, ['create_proof'])
|
|
39
|
+
const { stack } = await trie.findPath(trie['appliedKey'](key))
|
|
40
|
+
const p = stack.map((stackElem) => {
|
|
41
|
+
return stackElem.serialize()
|
|
42
|
+
})
|
|
43
|
+
trie['DEBUG'] && trie['debug'](`Proof created with (${stack.length}) nodes`, ['create_proof'])
|
|
44
|
+
return p
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Updates a trie from a proof by putting all the nodes in the proof into the trie. Pass {@param shouldVerifyRoot} as true to check
|
|
49
|
+
* that root key of proof matches root of trie and throw if not.
|
|
50
|
+
* An (EIP-1186)[https://eips.ethereum.org/EIPS/eip-1186] proof contains the encoded trie nodes from the root node to the leaf node storing state data.
|
|
51
|
+
* @param trie The trie to update from the proof.
|
|
52
|
+
* @param proof An (EIP-1186)[https://eips.ethereum.org/EIPS/eip-1186] proof to update the trie from.
|
|
53
|
+
* @param shouldVerifyRoot - defaults to false. If `true`, verifies that the root key of the proof matches the trie root and throws if not (i.e invalid proof).
|
|
54
|
+
* @returns The root of the proof
|
|
55
|
+
*/
|
|
56
|
+
export async function updateMPTFromMerkleProof(
|
|
57
|
+
trie: MerklePatriciaTrie,
|
|
58
|
+
proof: Proof,
|
|
59
|
+
shouldVerifyRoot: boolean = false,
|
|
60
|
+
) {
|
|
61
|
+
trie['DEBUG'] && trie['debug'](`Saving (${proof.length}) proof nodes in DB`, ['from_proof'])
|
|
62
|
+
const opStack = proof.map((nodeValue) => {
|
|
63
|
+
let key = Uint8Array.from(trie['hash'](nodeValue))
|
|
64
|
+
key = trie['_opts'].keyPrefix ? concatBytes(trie['_opts'].keyPrefix, key) : key
|
|
65
|
+
return {
|
|
66
|
+
type: 'put',
|
|
67
|
+
key,
|
|
68
|
+
value: nodeValue,
|
|
69
|
+
} as PutBatch
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
if (shouldVerifyRoot) {
|
|
73
|
+
if (opStack[0] !== undefined && opStack[0] !== null) {
|
|
74
|
+
if (!equalsBytes(trie.root(), opStack[0].key)) {
|
|
75
|
+
throw EthereumJSErrorWithoutCode('The provided proof does not have the expected trie root')
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await trie['_db'].batch(opStack)
|
|
81
|
+
if (opStack[0] !== undefined) {
|
|
82
|
+
return opStack[0].key
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Verifies a proof by putting all of its nodes into a trie and attempting to get the proven key. An (EIP-1186)[https://eips.ethereum.org/EIPS/eip-1186] proof
|
|
88
|
+
* contains the encoded trie nodes from the root node to the leaf node storing state data.
|
|
89
|
+
* @param trie The trie to verify the proof against
|
|
90
|
+
* @param rootHash Root hash of the trie that this proof was created from and is being verified for
|
|
91
|
+
* @param key Key that is being verified and that the proof is created for
|
|
92
|
+
* @param proof an EIP-1186 proof to verify the key against
|
|
93
|
+
* @throws If proof is found to be invalid.
|
|
94
|
+
* @returns The value from the key, or null if valid proof of non-existence.
|
|
95
|
+
*/
|
|
96
|
+
export async function verifyMPTWithMerkleProof(
|
|
97
|
+
trie: MerklePatriciaTrie,
|
|
98
|
+
rootHash: Uint8Array,
|
|
99
|
+
key: Uint8Array,
|
|
100
|
+
proof: Proof,
|
|
101
|
+
): Promise<Uint8Array | null> {
|
|
102
|
+
trie['DEBUG'] &&
|
|
103
|
+
trie['debug'](
|
|
104
|
+
`Verifying Proof:\n|| Key: ${bytesToHex(key)}\n|| Root: ${bytesToHex(
|
|
105
|
+
rootHash,
|
|
106
|
+
)}\n|| Proof: (${proof.length}) nodes
|
|
107
|
+
`,
|
|
108
|
+
['VERIFY_PROOF'],
|
|
109
|
+
)
|
|
110
|
+
const proofTrie = new MerklePatriciaTrie({
|
|
111
|
+
root: rootHash,
|
|
112
|
+
useKeyHashingFunction: trie['_opts'].useKeyHashingFunction,
|
|
113
|
+
common: trie['_opts'].common,
|
|
114
|
+
})
|
|
115
|
+
try {
|
|
116
|
+
await updateMPTFromMerkleProof(proofTrie, proof, true)
|
|
117
|
+
} catch {
|
|
118
|
+
throw EthereumJSErrorWithoutCode('Invalid proof nodes given')
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
trie['DEBUG'] &&
|
|
122
|
+
trie['debug'](`Verifying proof by retrieving key: ${bytesToHex(key)} from proof trie`, [
|
|
123
|
+
'VERIFY_PROOF',
|
|
124
|
+
])
|
|
125
|
+
const value = await proofTrie.get(trie['appliedKey'](key), true)
|
|
126
|
+
trie['DEBUG'] && trie['debug'](`PROOF VERIFIED`, ['VERIFY_PROOF'])
|
|
127
|
+
return value
|
|
128
|
+
} catch (err: any) {
|
|
129
|
+
if (err.message === 'Missing node in DB') {
|
|
130
|
+
throw EthereumJSErrorWithoutCode('Invalid proof provided')
|
|
131
|
+
} else {
|
|
132
|
+
throw err
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|