@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.
Files changed (204) hide show
  1. package/README.md +448 -0
  2. package/dist/cjs/constructors.d.ts +12 -0
  3. package/dist/cjs/constructors.d.ts.map +1 -0
  4. package/dist/cjs/constructors.js +57 -0
  5. package/dist/cjs/constructors.js.map +1 -0
  6. package/dist/cjs/db/checkpointDB.d.ts +87 -0
  7. package/dist/cjs/db/checkpointDB.d.ts.map +1 -0
  8. package/dist/cjs/db/checkpointDB.js +258 -0
  9. package/dist/cjs/db/checkpointDB.js.map +1 -0
  10. package/dist/cjs/db/index.d.ts +2 -0
  11. package/dist/cjs/db/index.d.ts.map +1 -0
  12. package/dist/cjs/db/index.js +18 -0
  13. package/dist/cjs/db/index.js.map +1 -0
  14. package/dist/cjs/index.d.ts +8 -0
  15. package/dist/cjs/index.d.ts.map +1 -0
  16. package/dist/cjs/index.js +24 -0
  17. package/dist/cjs/index.js.map +1 -0
  18. package/dist/cjs/mpt.d.ts +261 -0
  19. package/dist/cjs/mpt.d.ts.map +1 -0
  20. package/dist/cjs/mpt.js +900 -0
  21. package/dist/cjs/mpt.js.map +1 -0
  22. package/dist/cjs/node/branch.d.ts +14 -0
  23. package/dist/cjs/node/branch.d.ts.map +1 -0
  24. package/dist/cjs/node/branch.js +52 -0
  25. package/dist/cjs/node/branch.js.map +1 -0
  26. package/dist/cjs/node/extension.d.ts +7 -0
  27. package/dist/cjs/node/extension.d.ts.map +1 -0
  28. package/dist/cjs/node/extension.js +14 -0
  29. package/dist/cjs/node/extension.js.map +1 -0
  30. package/dist/cjs/node/extensionOrLeafNodeBase.d.ts +15 -0
  31. package/dist/cjs/node/extensionOrLeafNodeBase.d.ts.map +1 -0
  32. package/dist/cjs/node/extensionOrLeafNodeBase.js +42 -0
  33. package/dist/cjs/node/extensionOrLeafNodeBase.js.map +1 -0
  34. package/dist/cjs/node/index.d.ts +5 -0
  35. package/dist/cjs/node/index.d.ts.map +1 -0
  36. package/dist/cjs/node/index.js +21 -0
  37. package/dist/cjs/node/index.js.map +1 -0
  38. package/dist/cjs/node/leaf.d.ts +7 -0
  39. package/dist/cjs/node/leaf.d.ts.map +1 -0
  40. package/dist/cjs/node/leaf.js +14 -0
  41. package/dist/cjs/node/leaf.js.map +1 -0
  42. package/dist/cjs/node/util.d.ts +8 -0
  43. package/dist/cjs/node/util.d.ts.map +1 -0
  44. package/dist/cjs/node/util.js +38 -0
  45. package/dist/cjs/node/util.js.map +1 -0
  46. package/dist/cjs/package.json +3 -0
  47. package/dist/cjs/proof/index.d.ts +3 -0
  48. package/dist/cjs/proof/index.d.ts.map +1 -0
  49. package/dist/cjs/proof/index.js +19 -0
  50. package/dist/cjs/proof/index.js.map +1 -0
  51. package/dist/cjs/proof/proof.d.ts +41 -0
  52. package/dist/cjs/proof/proof.d.ts.map +1 -0
  53. package/dist/cjs/proof/proof.js +119 -0
  54. package/dist/cjs/proof/proof.js.map +1 -0
  55. package/dist/cjs/proof/range.d.ts +35 -0
  56. package/dist/cjs/proof/range.d.ts.map +1 -0
  57. package/dist/cjs/proof/range.js +456 -0
  58. package/dist/cjs/proof/range.js.map +1 -0
  59. package/dist/cjs/types.d.ts +110 -0
  60. package/dist/cjs/types.d.ts.map +1 -0
  61. package/dist/cjs/types.js +6 -0
  62. package/dist/cjs/types.js.map +1 -0
  63. package/dist/cjs/util/asyncWalk.d.ts +20 -0
  64. package/dist/cjs/util/asyncWalk.d.ts.map +1 -0
  65. package/dist/cjs/util/asyncWalk.js +50 -0
  66. package/dist/cjs/util/asyncWalk.js.map +1 -0
  67. package/dist/cjs/util/encoding.d.ts +31 -0
  68. package/dist/cjs/util/encoding.d.ts.map +1 -0
  69. package/dist/cjs/util/encoding.js +200 -0
  70. package/dist/cjs/util/encoding.js.map +1 -0
  71. package/dist/cjs/util/genesisState.d.ts +6 -0
  72. package/dist/cjs/util/genesisState.d.ts.map +1 -0
  73. package/dist/cjs/util/genesisState.js +45 -0
  74. package/dist/cjs/util/genesisState.js.map +1 -0
  75. package/dist/cjs/util/hex.d.ts +20 -0
  76. package/dist/cjs/util/hex.d.ts.map +1 -0
  77. package/dist/cjs/util/hex.js +48 -0
  78. package/dist/cjs/util/hex.js.map +1 -0
  79. package/dist/cjs/util/index.d.ts +4 -0
  80. package/dist/cjs/util/index.d.ts.map +1 -0
  81. package/dist/cjs/util/index.js +20 -0
  82. package/dist/cjs/util/index.js.map +1 -0
  83. package/dist/cjs/util/nibbles.d.ts +30 -0
  84. package/dist/cjs/util/nibbles.d.ts.map +1 -0
  85. package/dist/cjs/util/nibbles.js +79 -0
  86. package/dist/cjs/util/nibbles.js.map +1 -0
  87. package/dist/cjs/util/walkController.d.ts +72 -0
  88. package/dist/cjs/util/walkController.d.ts.map +1 -0
  89. package/dist/cjs/util/walkController.js +138 -0
  90. package/dist/cjs/util/walkController.js.map +1 -0
  91. package/dist/esm/constructors.d.ts +12 -0
  92. package/dist/esm/constructors.d.ts.map +1 -0
  93. package/dist/esm/constructors.js +53 -0
  94. package/dist/esm/constructors.js.map +1 -0
  95. package/dist/esm/db/checkpointDB.d.ts +87 -0
  96. package/dist/esm/db/checkpointDB.d.ts.map +1 -0
  97. package/dist/esm/db/checkpointDB.js +254 -0
  98. package/dist/esm/db/checkpointDB.js.map +1 -0
  99. package/dist/esm/db/index.d.ts +2 -0
  100. package/dist/esm/db/index.d.ts.map +1 -0
  101. package/dist/esm/db/index.js +2 -0
  102. package/dist/esm/db/index.js.map +1 -0
  103. package/dist/esm/index.d.ts +8 -0
  104. package/dist/esm/index.d.ts.map +1 -0
  105. package/dist/esm/index.js +8 -0
  106. package/dist/esm/index.js.map +1 -0
  107. package/dist/esm/mpt.d.ts +261 -0
  108. package/dist/esm/mpt.d.ts.map +1 -0
  109. package/dist/esm/mpt.js +897 -0
  110. package/dist/esm/mpt.js.map +1 -0
  111. package/dist/esm/node/branch.d.ts +14 -0
  112. package/dist/esm/node/branch.d.ts.map +1 -0
  113. package/dist/esm/node/branch.js +48 -0
  114. package/dist/esm/node/branch.js.map +1 -0
  115. package/dist/esm/node/extension.d.ts +7 -0
  116. package/dist/esm/node/extension.d.ts.map +1 -0
  117. package/dist/esm/node/extension.js +10 -0
  118. package/dist/esm/node/extension.js.map +1 -0
  119. package/dist/esm/node/extensionOrLeafNodeBase.d.ts +15 -0
  120. package/dist/esm/node/extensionOrLeafNodeBase.d.ts.map +1 -0
  121. package/dist/esm/node/extensionOrLeafNodeBase.js +38 -0
  122. package/dist/esm/node/extensionOrLeafNodeBase.js.map +1 -0
  123. package/dist/esm/node/index.d.ts +5 -0
  124. package/dist/esm/node/index.d.ts.map +1 -0
  125. package/dist/esm/node/index.js +5 -0
  126. package/dist/esm/node/index.js.map +1 -0
  127. package/dist/esm/node/leaf.d.ts +7 -0
  128. package/dist/esm/node/leaf.d.ts.map +1 -0
  129. package/dist/esm/node/leaf.js +10 -0
  130. package/dist/esm/node/leaf.js.map +1 -0
  131. package/dist/esm/node/util.d.ts +8 -0
  132. package/dist/esm/node/util.d.ts.map +1 -0
  133. package/dist/esm/node/util.js +33 -0
  134. package/dist/esm/node/util.js.map +1 -0
  135. package/dist/esm/package.json +3 -0
  136. package/dist/esm/proof/index.d.ts +3 -0
  137. package/dist/esm/proof/index.d.ts.map +1 -0
  138. package/dist/esm/proof/index.js +3 -0
  139. package/dist/esm/proof/index.js.map +1 -0
  140. package/dist/esm/proof/proof.d.ts +41 -0
  141. package/dist/esm/proof/proof.d.ts.map +1 -0
  142. package/dist/esm/proof/proof.js +113 -0
  143. package/dist/esm/proof/proof.js.map +1 -0
  144. package/dist/esm/proof/range.d.ts +35 -0
  145. package/dist/esm/proof/range.d.ts.map +1 -0
  146. package/dist/esm/proof/range.js +453 -0
  147. package/dist/esm/proof/range.js.map +1 -0
  148. package/dist/esm/types.d.ts +110 -0
  149. package/dist/esm/types.d.ts.map +1 -0
  150. package/dist/esm/types.js +3 -0
  151. package/dist/esm/types.js.map +1 -0
  152. package/dist/esm/util/asyncWalk.d.ts +20 -0
  153. package/dist/esm/util/asyncWalk.d.ts.map +1 -0
  154. package/dist/esm/util/asyncWalk.js +47 -0
  155. package/dist/esm/util/asyncWalk.js.map +1 -0
  156. package/dist/esm/util/encoding.d.ts +31 -0
  157. package/dist/esm/util/encoding.d.ts.map +1 -0
  158. package/dist/esm/util/encoding.js +188 -0
  159. package/dist/esm/util/encoding.js.map +1 -0
  160. package/dist/esm/util/genesisState.d.ts +6 -0
  161. package/dist/esm/util/genesisState.d.ts.map +1 -0
  162. package/dist/esm/util/genesisState.js +42 -0
  163. package/dist/esm/util/genesisState.js.map +1 -0
  164. package/dist/esm/util/hex.d.ts +20 -0
  165. package/dist/esm/util/hex.d.ts.map +1 -0
  166. package/dist/esm/util/hex.js +43 -0
  167. package/dist/esm/util/hex.js.map +1 -0
  168. package/dist/esm/util/index.d.ts +4 -0
  169. package/dist/esm/util/index.d.ts.map +1 -0
  170. package/dist/esm/util/index.js +4 -0
  171. package/dist/esm/util/index.js.map +1 -0
  172. package/dist/esm/util/nibbles.d.ts +30 -0
  173. package/dist/esm/util/nibbles.d.ts.map +1 -0
  174. package/dist/esm/util/nibbles.js +73 -0
  175. package/dist/esm/util/nibbles.js.map +1 -0
  176. package/dist/esm/util/walkController.d.ts +72 -0
  177. package/dist/esm/util/walkController.d.ts.map +1 -0
  178. package/dist/esm/util/walkController.js +134 -0
  179. package/dist/esm/util/walkController.js.map +1 -0
  180. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  181. package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
  182. package/package.json +85 -0
  183. package/src/constructors.ts +71 -0
  184. package/src/db/checkpointDB.ts +298 -0
  185. package/src/db/index.ts +1 -0
  186. package/src/index.ts +7 -0
  187. package/src/mpt.ts +1090 -0
  188. package/src/node/branch.ts +60 -0
  189. package/src/node/extension.ts +13 -0
  190. package/src/node/extensionOrLeafNodeBase.ts +54 -0
  191. package/src/node/index.ts +4 -0
  192. package/src/node/leaf.ts +13 -0
  193. package/src/node/util.ts +35 -0
  194. package/src/proof/index.ts +2 -0
  195. package/src/proof/proof.ts +135 -0
  196. package/src/proof/range.ts +542 -0
  197. package/src/types.ts +151 -0
  198. package/src/util/asyncWalk.ts +60 -0
  199. package/src/util/encoding.ts +209 -0
  200. package/src/util/genesisState.ts +52 -0
  201. package/src/util/hex.ts +47 -0
  202. package/src/util/index.ts +3 -0
  203. package/src/util/nibbles.ts +80 -0
  204. 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
+ }
@@ -0,0 +1,4 @@
1
+ export * from './branch.ts'
2
+ export * from './extension.ts'
3
+ export * from './leaf.ts'
4
+ export * from './util.ts'
@@ -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
+ }
@@ -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,2 @@
1
+ export * from './proof.ts'
2
+ export * from './range.ts'
@@ -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
+ }