1 | import { keccak256 } from 'ethereumjs-util'
|
2 | import { CheckpointTrie } from './checkpointTrie'
|
3 | import { Proof } from './baseTrie'
|
4 |
|
5 | /**
|
6 | * You can create a secure Trie where the keys are automatically hashed
|
7 | * using **keccak256** by using `import { SecureTrie as Trie } from 'merkle-patricia-tree'`.
|
8 | * It has the same methods and constructor as `Trie`.
|
9 | * @class SecureTrie
|
10 | * @extends Trie
|
11 | * @public
|
12 | */
|
13 | export class SecureTrie extends CheckpointTrie {
|
14 | constructor(...args: any) {
|
15 | super(...args)
|
16 | }
|
17 |
|
18 | /**
|
19 | * Gets a value given a `key`
|
20 | * @param key - the key to search for
|
21 | * @returns A Promise that resolves to `Buffer` if a value was found or `null` if no value was found.
|
22 | */
|
23 | async get(key: Buffer): Promise<Buffer | null> {
|
24 | const hash = keccak256(key)
|
25 | const value = await super.get(hash)
|
26 | return value
|
27 | }
|
28 |
|
29 | /**
|
30 | * Stores a given `value` at the given `key`.
|
31 | * For a falsey value, use the original key to avoid double hashing the key.
|
32 | * @param key
|
33 | * @param value
|
34 | */
|
35 | async put(key: Buffer, val: Buffer): Promise<void> {
|
36 | if (!val || val.toString() === '') {
|
37 | await this.del(key)
|
38 | } else {
|
39 | const hash = keccak256(key)
|
40 | await super.put(hash, val)
|
41 | }
|
42 | }
|
43 |
|
44 | /**
|
45 | * Deletes a value given a `key`.
|
46 | * @param key
|
47 | */
|
48 | async del(key: Buffer): Promise<void> {
|
49 | const hash = keccak256(key)
|
50 | await super.del(hash)
|
51 | }
|
52 |
|
53 | /**
|
54 | * prove has been renamed to {@link SecureTrie.createProof}.
|
55 | * @deprecated
|
56 | * @param trie
|
57 | * @param key
|
58 | */
|
59 | static async prove(trie: SecureTrie, key: Buffer): Promise<Proof> {
|
60 | return this.createProof(trie, key)
|
61 | }
|
62 |
|
63 | /**
|
64 | * Creates a proof that can be verified using {@link SecureTrie.verifyProof}.
|
65 | * @param trie
|
66 | * @param key
|
67 | */
|
68 | static createProof(trie: SecureTrie, key: Buffer): Promise<Proof> {
|
69 | const hash = keccak256(key)
|
70 | return super.createProof(trie, hash)
|
71 | }
|
72 |
|
73 | /**
|
74 | * Verifies a proof.
|
75 | * @param rootHash
|
76 | * @param key
|
77 | * @param proof
|
78 | * @throws If proof is found to be invalid.
|
79 | * @returns The value from the key.
|
80 | */
|
81 | static async verifyProof(rootHash: Buffer, key: Buffer, proof: Proof): Promise<Buffer | null> {
|
82 | const hash = keccak256(key)
|
83 | return super.verifyProof(rootHash, hash, proof)
|
84 | }
|
85 |
|
86 | /**
|
87 | * Returns a copy of the underlying trie with the interface of SecureTrie.
|
88 | * @param includeCheckpoints - If true and during a checkpoint, the copy will contain the checkpointing metadata and will use the same scratch as underlying db.
|
89 | */
|
90 | copy(includeCheckpoints = true): SecureTrie {
|
91 | const db = this.db.copy()
|
92 | const secureTrie = new SecureTrie(db._leveldb, this.root)
|
93 | if (includeCheckpoints && this.isCheckpoint) {
|
94 | secureTrie.db.checkpoints = [...this.db.checkpoints]
|
95 | }
|
96 | return secureTrie
|
97 | }
|
98 | }
|