nimbus-eth1/nimbus/db/distinct_tries.nim
Jordan Hrycaj 221e6c9e2f
Unified database frontend integration (#1670)
* Nimbus folder environment update

details:
* Integrated `CoreDbRef` for the sources in the `nimbus` sub-folder.
* The `nimbus` program does not compile yet as it needs the updates
  in the parallel `stateless` sub-folder.

* Stateless environment update

details:
* Integrated `CoreDbRef` for the sources in the `stateless` sub-folder.
* The `nimbus` program compiles now.

* Premix environment update

details:
* Integrated `CoreDbRef` for the sources in the `premix` sub-folder.

* Fluffy environment update

details:
* Integrated `CoreDbRef` for the sources in the `fluffy` sub-folder.

* Tools environment update

details:
* Integrated `CoreDbRef` for the sources in the `tools` sub-folder.

* Nodocker environment update

details:
* Integrated `CoreDbRef` for the sources in the
  `hive_integration/nodocker` sub-folder.

* Tests environment update

details:
* Integrated `CoreDbRef` for the sources in the `tests` sub-folder.
* The unit tests compile and run cleanly now.

* Generalise `CoreDbRef` to any `select_backend` supported database

why:
  Generalisation was just missed due to overcoming some compiler oddity
  which was tied to rocksdb for testing.

* Suppress compiler warning for `newChainDB()`

why:
  Warning was added to this function which must be wrapped so that
  any `CatchableError` is re-raised as `Defect`.

* Split off persistent `CoreDbRef` constructor into separate file

why:
  This allows to compile a memory only database version without linking
  the backend library.

* Use memory `CoreDbRef` database by default

detail:
 Persistent DB constructor needs to import `db/core_db/persistent

why:
 Most tests use memory DB anyway. This avoids linking `-lrocksdb` or
 any other backend by default.

* fix `toLegacyBackend()` availability check

why:
  got garbled after memory/persistent split.

* Clarify raw access to MPT for snap sync handler

why:
  Logically, `kvt` is not the raw access for the hexary trie (although
  this holds for the legacy database)
2023-08-04 12:10:09 +01:00

84 lines
3.5 KiB
Nim

# The point of this file is just to give a little more type-safety
# and clarity to our use of SecureHexaryTrie, by having distinct
# types for the big trie containing all the accounts and the little
# tries containing the storage for an individual account.
#
# It's nice to have all the accesses go through "getAccountBytes"
# rather than just "get" (which is hard to search for). Plus we
# may want to put in assertions to make sure that the nodes for
# the account are all present (in stateless mode), etc.
import
std/typetraits,
eth/common,
./core_db
type
DB = CoreDbRef
AccountsTrie* = distinct CoreDbPhkRef
StorageTrie* = distinct CoreDbPhkRef
# I don't understand why "borrow" doesn't work here. --Adam
proc rootHash* (trie: AccountsTrie | StorageTrie): KeccakHash = distinctBase(trie).rootHash
proc rootHashHex*(trie: AccountsTrie | StorageTrie): string = $trie.rootHash
proc db* (trie: AccountsTrie | StorageTrie): DB = distinctBase(trie).parent
proc isPruning* (trie: AccountsTrie | StorageTrie): bool = distinctBase(trie).isPruning
proc mpt* (trie: AccountsTrie | StorageTrie): CoreDbMptRef = distinctBase(trie).toMpt
proc phk* (trie: AccountsTrie | StorageTrie): CoreDbPhkRef = distinctBase(trie)
template initAccountsTrie*(db: DB, rootHash: KeccakHash, isPruning = true): AccountsTrie =
AccountsTrie(db.phkPrune(rootHash, isPruning))
template initAccountsTrie*(db: DB, isPruning = true): AccountsTrie =
AccountsTrie(db.phkPrune(isPruning))
proc getAccountBytes*(trie: AccountsTrie, address: EthAddress): seq[byte] =
CoreDbPhkRef(trie).get(address)
proc maybeGetAccountBytes*(trie: AccountsTrie, address: EthAddress): Option[seq[byte]] =
CoreDbPhkRef(trie).maybeGet(address)
proc putAccountBytes*(trie: var AccountsTrie, address: EthAddress, value: openArray[byte]) =
CoreDbPhkRef(trie).put(address, value)
proc delAccountBytes*(trie: var AccountsTrie, address: EthAddress) =
CoreDbPhkRef(trie).del(address)
template initStorageTrie*(db: DB, rootHash: KeccakHash, isPruning = true): StorageTrie =
StorageTrie(db.phkPrune(rootHash, isPruning))
template initStorageTrie*(db: DB, isPruning = true): StorageTrie =
StorageTrie(db.phkPrune(isPruning))
template createTrieKeyFromSlot*(slot: UInt256): auto =
# XXX: This is too expensive. Similar to `createRangeFromAddress`
# Converts a number to hex big-endian representation including
# prefix and leading zeros:
slot.toByteArrayBE
# Original py-evm code:
# pad32(int_to_big_endian(slot))
# morally equivalent to toByteRange_Unnecessary but with different types
proc getSlotBytes*(trie: StorageTrie, slotAsKey: openArray[byte]): seq[byte] =
CoreDbPhkRef(trie).get(slotAsKey)
proc maybeGetSlotBytes*(trie: StorageTrie, slotAsKey: openArray[byte]): Option[seq[byte]] =
CoreDbPhkRef(trie).maybeGet(slotAsKey)
proc putSlotBytes*(trie: var StorageTrie, slotAsKey: openArray[byte], value: openArray[byte]) =
CoreDbPhkRef(trie).put(slotAsKey, value)
proc delSlotBytes*(trie: var StorageTrie, slotAsKey: openArray[byte]) =
CoreDbPhkRef(trie).del(slotAsKey)
proc storageTrieForAccount*(trie: AccountsTrie, account: Account, isPruning = true): StorageTrie =
# TODO: implement `prefix-db` to solve issue #228 permanently.
# the `prefix-db` will automatically insert account address to the
# underlying-db key without disturb how the trie works.
# it will create virtual container for each account.
# see nim-eth#9
initStorageTrie(trie.db, account.storageRoot, isPruning)