nimbus-eth1/nimbus/db/core_db
Jordan Hrycaj 0f430c70fd
Aristo avoid storage trie update race conditions (#2251)
* Update TDD suite logger output format choices

why:
  New format is not practical for TDD as it just dumps data across a wide
  range (considerably larder than 80 columns.)

  So the new format can be turned on by function argument.

* Update unit tests samples configuration

why:
  Slightly changed the way to find the `era1` directory

* Remove compiler warnings (fix deprecated expressions and phrases)

* Update `Aristo` debugging tools

* Always update the `storageID` field of account leaf vertices

why:
  Storage tries are weekly linked to an account leaf object in that
  the `storageID` field is updated by the application.

  Previously, `Aristo` verified that leaf objects make sense when passed
  to the database. As a consequence
  * the database was inconsistent for a short while
  * the burden for correctness was all on the application which led
    to delayed error handling which is hard to debug.

  So `Aristo` will internally update the account leaf objects so that
  there are no race conditions due to the storage trie handling

* Aristo: Let `stow()`/`persist()` bail out unless there is a `VertexID(1)`

why:
  The journal and filter logic depends on the hash of the `VertexID(1)`
  which is commonly known as the state root. This implies that all
  changes to the database are somehow related to that.

* Make sure that a `Ledger` account does not overwrite the storage trie reference

why:
  Due to the abstraction of a sub-trie (now referred to as column with a
  hash describing its state) there was a weakness in the `Aristo` handler
  where an account leaf could be overwritten though changing the validity
  of the database. This has been changed and the database will now reject
  such changes.

  This patch fixes the behaviour on the application layer. In particular,
  the column handle returned by the `CoreDb` needs to be updated by
  the `Aristo` database state. This mitigates the problem that a storage
  trie might have vanished or re-apperaed with a different vertex ID.

* Fix sub-trie deletion test

why:
  Was originally hinged on `VertexID(1)` which cannot be wholesale
  deleted anymore after the last Aristo update. Also, running with
  `VertexID(2)` needs an artificial `VertexID(1)` for making `stow()`
  or `persist()` work.

* Cosmetics

* Activate `test_generalstate_json`

* Temporarily `deactivate test_tracer_json`

* Fix copyright header

---------

Co-authored-by: jordan <jordan@dry.pudding>
Co-authored-by: Jacek Sieka <jacek@status.im>
2024-05-30 17:48:38 +00:00
..
backend Aristo avoid storage trie update race conditions (#2251) 2024-05-30 17:48:38 +00:00
base restore a few tests, cleanup (#2234) 2024-05-28 14:49:35 +02:00
README.md Core db+aristo provides tracer funtionality (#2089) 2024-03-21 10:45:57 +00:00
TODO.md Aristo resume off line syncing on pre loaded database (#2203) 2024-05-22 13:41:14 +00:00
base.nim restore a few tests, cleanup (#2234) 2024-05-28 14:49:35 +02:00
base_iterators.nim Culling legacy DB and accounts cache (#2197) 2024-05-20 10:17:51 +00:00
base_iterators_persistent.nim Culling legacy DB and accounts cache (#2197) 2024-05-20 10:17:51 +00:00
core_apps_newapi.nim restore a few tests, cleanup (#2234) 2024-05-28 14:49:35 +02:00
memory_only.nim Culling legacy DB and accounts cache (#2197) 2024-05-20 10:17:51 +00:00
persistent.nim Culling legacy DB and accounts cache (#2197) 2024-05-20 10:17:51 +00:00

README.md

Core database replacement wrapper object

This wrapper replaces the TrieDatabaseRef and its derivatives by the new object CoreDbRef.

Relations to current TrieDatabaseRef implementation

Here are some incomplete translations for objects and constructors.

Object types:

Legacy notation CoreDbRef based replacement
ChainDB (don't use/avoid)
ChainDbRef CoreDbRef
TrieDatabaseRef CoreDbKvtRef
HexaryTrie CoreDbMptRef
SecureHexaryTrie CoreDbPhkRef
DbTransaction CoreDbTxRef
TransactionID CoreDbTxID

Constructors:

Legacy notation CoreDbRef based replacement
trieDB newChainDB("..") newCoreDbRef(LegacyDbPersistent,"..")
newMemoryDB() newCoreDbRef(LegacyDbMemory)
--
initHexaryTrie(db,..) db.mpt(..) (no pruning)
db.mptPrune(..) (w/pruning true/false)
--
initSecureHexaryTrie(db,..) db.phk(..) (no pruning)
db.phkPrune(..) (w/pruning true/false)
--
newCaptureDB(db,memDB) db.capture() (see below)

Usage of the replacement wrapper

Objects pedigree:

    CoreDbRef                        -- base descriptor
     | | |
     | | +--- CoreDbCtxRef           -- MPT context descriptor
     | |        | |
     | |        | +-- CoreDbMptRef   -- hexary trie instance
     | |        | |    :                    :
     | |        | +-- CoreDbMptRef   -- hexary trie instance
     | |        |
     | |        |
     | |        +---- CoreDbPhkRef   -- pre-hashed key hexary trie instance
     | |        |      :                    :
     | |        +---- CoreDbPhkRef   -- pre-hashed key hexary trie instance
     | |
     | |
     | +------ CoreDbKvtRef          -- single static key-value table
     |
     |
     +-------- CoreDbCaptRef         -- tracer support descriptor

Instantiating legacy standard database object descriptors works as follows:

    let
      db = newCoreDbRef(..)           # new base descriptor
      mpt = db.mpt(..)                # hexary trie/Merkle Patricia Tree
      phk = db.phk(..)                # pre-hashed key hexary trie/MPT
      kvt = db.kvt                    # key-value table

Tracer support setup by hiding the current CoreDbRef behind a replacement:

    let
      capture = db.capture()
      db = capture.recorder           # use the recorder in place of db
    ...

    for key,value in capture.recorder.kvt:
     ...                              # process recorded data