Culling legacy DB and accounts cache (#2197)
details: + Compiles nimbus all_tests + Failing tests have been commented out
This commit is contained in:
parent
38eaebc5c7
commit
ee9aea171d
|
@ -22,7 +22,6 @@ proc processChainData(cd: ChainData): TestStatus =
|
|||
let
|
||||
networkId = NetworkId(cd.params.config.chainId)
|
||||
com = CommonRef.new(newCoreDbRef DefaultDbMemory,
|
||||
pruneTrie = false,
|
||||
networkId,
|
||||
cd.params
|
||||
)
|
||||
|
|
|
@ -61,8 +61,7 @@ const
|
|||
|
||||
proc makeCom*(conf: NimbusConf): CommonRef =
|
||||
CommonRef.new(
|
||||
newCoreDbRef LegacyDbMemory,
|
||||
conf.chainDbMode == ChainDbMode.Prune,
|
||||
newCoreDbRef DefaultDbMemory,
|
||||
conf.networkId,
|
||||
conf.networkParams
|
||||
)
|
||||
|
|
|
@ -78,8 +78,7 @@ proc main() =
|
|||
conf = makeConfig(@["--custom-network:" & genesisFile])
|
||||
ethCtx = newEthContext()
|
||||
ethNode = setupEthNode(conf, ethCtx, eth)
|
||||
com = CommonRef.new(newCoreDbRef LegacyDbMemory,
|
||||
pruneTrie = false,
|
||||
com = CommonRef.new(newCoreDbRef DefaultDbMemory,
|
||||
conf.networkId,
|
||||
conf.networkParams
|
||||
)
|
||||
|
|
|
@ -47,17 +47,16 @@ proc genesisHeader(node: JsonNode): BlockHeader =
|
|||
rlp.decode(genesisRLP, EthBlock).header
|
||||
|
||||
proc setupELClient*(t: TestEnv, conf: ChainConfig, node: JsonNode) =
|
||||
let memDB = newCoreDbRef LegacyDbMemory
|
||||
let memDB = newCoreDbRef DefaultDbMemory
|
||||
t.ctx = newEthContext()
|
||||
t.ethNode = setupEthNode(t.conf, t.ctx, eth)
|
||||
t.com = CommonRef.new(
|
||||
memDB,
|
||||
conf,
|
||||
t.conf.chainDbMode == ChainDbMode.Prune
|
||||
conf
|
||||
)
|
||||
t.chainRef = newChain(t.com, extraValidation = true)
|
||||
let
|
||||
stateDB = AccountsCache.init(memDB, emptyRlpHash, t.conf.chainDbMode == ChainDbMode.Prune)
|
||||
stateDB = LedgerCache.init(memDB, emptyRlpHash)
|
||||
genesisHeader = node.genesisHeader
|
||||
|
||||
setupStateDB(node["pre"], stateDB)
|
||||
|
|
|
@ -76,8 +76,7 @@ proc setupEnv*(): TestEnv =
|
|||
let
|
||||
ethCtx = newEthContext()
|
||||
ethNode = setupEthNode(conf, ethCtx, eth)
|
||||
com = CommonRef.new(newCoreDbRef LegacyDbMemory,
|
||||
conf.chainDbMode == ChainDbMode.Prune,
|
||||
com = CommonRef.new(newCoreDbRef DefaultDbMemory,
|
||||
conf.networkId,
|
||||
conf.networkParams
|
||||
)
|
||||
|
|
|
@ -46,9 +46,6 @@ type
|
|||
# all purpose storage
|
||||
db: CoreDbRef
|
||||
|
||||
# prune underlying state db?
|
||||
pruneTrie: bool
|
||||
|
||||
# block chain config
|
||||
config: ChainConfig
|
||||
|
||||
|
@ -103,10 +100,8 @@ type
|
|||
ldgType: LedgerType
|
||||
## Optional suggestion for the ledger cache to be used as state DB
|
||||
|
||||
const
|
||||
CommonLegacyDbLedgerTypeDefault = LegacyAccountsCache
|
||||
## Default ledger type to use, see `ldgType` above. This default will be
|
||||
## superseded by `LedgerCache` as default for `Aristo` type deb backend.
|
||||
pruneHistory: bool
|
||||
## Must not not set for a full node, might go away some time
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Forward declarations
|
||||
|
@ -147,31 +142,24 @@ proc daoCheck(conf: ChainConfig) =
|
|||
if conf.daoForkSupport and conf.daoForkBlock.isNone:
|
||||
conf.daoForkBlock = conf.homesteadBlock
|
||||
|
||||
proc init(com : CommonRef,
|
||||
db : CoreDbRef,
|
||||
pruneTrie: bool,
|
||||
networkId: NetworkId,
|
||||
config : ChainConfig,
|
||||
genesis : Genesis,
|
||||
ldgType : LedgerType,
|
||||
proc init(com : CommonRef,
|
||||
db : CoreDbRef,
|
||||
networkId : NetworkId,
|
||||
config : ChainConfig,
|
||||
genesis : Genesis,
|
||||
ldgType : LedgerType,
|
||||
pruneHistory: bool,
|
||||
) {.gcsafe, raises: [CatchableError].} =
|
||||
|
||||
config.daoCheck()
|
||||
|
||||
com.db = db
|
||||
com.pruneTrie = pruneTrie
|
||||
com.config = config
|
||||
com.forkTransitionTable = config.toForkTransitionTable()
|
||||
com.networkId = networkId
|
||||
com.syncProgress= SyncProgress()
|
||||
com.ldgType = block:
|
||||
if ldgType != LedgerType(0):
|
||||
ldgType
|
||||
elif db.dbType in {AristoDbMemory,AristoDbRocks,AristoDbVoid}:
|
||||
# The `Aristo` backend does not work well with the `LegacyAccountsCache`
|
||||
LedgerCache
|
||||
else:
|
||||
CommonLegacyDbLedgerTypeDefault
|
||||
com.ldgType = LedgerCache
|
||||
com.pruneHistory= pruneHistory
|
||||
|
||||
# Initalise the PoA state regardless of whether it is needed on the current
|
||||
# network. For non-PoA networks this descriptor is ignored.
|
||||
|
@ -235,10 +223,10 @@ proc getTdIfNecessary(com: CommonRef, blockHash: Hash256): Option[DifficultyInt]
|
|||
proc new*(
|
||||
_: type CommonRef;
|
||||
db: CoreDbRef;
|
||||
pruneTrie: bool = true;
|
||||
networkId: NetworkId = MainNet;
|
||||
params = networkParams(MainNet);
|
||||
ldgType = LedgerType(0);
|
||||
pruneHistory = false;
|
||||
): CommonRef
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
|
||||
|
@ -247,19 +235,19 @@ proc new*(
|
|||
new(result)
|
||||
result.init(
|
||||
db,
|
||||
pruneTrie,
|
||||
networkId,
|
||||
params.config,
|
||||
params.genesis,
|
||||
ldgType)
|
||||
ldgType,
|
||||
pruneHistory)
|
||||
|
||||
proc new*(
|
||||
_: type CommonRef;
|
||||
db: CoreDbRef;
|
||||
config: ChainConfig;
|
||||
pruneTrie: bool = true;
|
||||
networkId: NetworkId = MainNet;
|
||||
ldgType = LedgerType(0);
|
||||
pruneHistory = false;
|
||||
): CommonRef
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
|
||||
|
@ -268,18 +256,17 @@ proc new*(
|
|||
new(result)
|
||||
result.init(
|
||||
db,
|
||||
pruneTrie,
|
||||
networkId,
|
||||
config,
|
||||
nil,
|
||||
ldgType)
|
||||
ldgType,
|
||||
pruneHistory)
|
||||
|
||||
proc clone*(com: CommonRef, db: CoreDbRef): CommonRef =
|
||||
## clone but replace the db
|
||||
## used in EVM tracer whose db is CaptureDB
|
||||
CommonRef(
|
||||
db : db,
|
||||
pruneTrie : com.pruneTrie,
|
||||
config : com.config,
|
||||
forkTransitionTable: com.forkTransitionTable,
|
||||
forkIdCalculator: com.forkIdCalculator,
|
||||
|
@ -292,8 +279,8 @@ proc clone*(com: CommonRef, db: CoreDbRef): CommonRef =
|
|||
pow : com.pow,
|
||||
poa : com.poa,
|
||||
pos : com.pos,
|
||||
ldgType : com.ldgType
|
||||
)
|
||||
ldgType : com.ldgType,
|
||||
pruneHistory : com.pruneHistory)
|
||||
|
||||
proc clone*(com: CommonRef): CommonRef =
|
||||
com.clone(com.db)
|
||||
|
@ -492,8 +479,8 @@ func cliqueEpoch*(com: CommonRef): int =
|
|||
if com.config.clique.epoch.isSome:
|
||||
return com.config.clique.epoch.get()
|
||||
|
||||
func pruneTrie*(com: CommonRef): bool =
|
||||
com.pruneTrie
|
||||
func pruneHistory*(com: CommonRef): bool =
|
||||
com.pruneHistory
|
||||
|
||||
# always remember ChainId and NetworkId
|
||||
# are two distinct things that often got mixed
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
@ -13,8 +13,7 @@
|
|||
import
|
||||
std/tables,
|
||||
eth/[common, eip1559],
|
||||
eth/trie/trie_defs,
|
||||
../db/[ledger, core_db, state_db/read_write],
|
||||
../db/[ledger, core_db],
|
||||
../constants,
|
||||
./chain_config
|
||||
|
||||
|
@ -28,8 +27,6 @@ type
|
|||
address: EthAddress; nonce: AccountNonce; balance: UInt256;
|
||||
code: openArray[byte]) {.catchRaise.}
|
||||
|
||||
GenesisCompensateLegacySetupFn = proc() {.noRaise.}
|
||||
|
||||
GenesisSetStorageFn = proc(
|
||||
address: EthAddress; slot: UInt256; val: UInt256) {.rlpRaise.}
|
||||
|
||||
|
@ -40,70 +37,23 @@ type
|
|||
GenesisGetTrieFn = proc: CoreDbMptRef {.noRaise.}
|
||||
|
||||
GenesisLedgerRef* = ref object
|
||||
## Exportable ledger DB just for initialising Genesis. This is needed
|
||||
## when using the `Aristo` backend which is not fully supported by the
|
||||
## `AccountStateDB` object.
|
||||
##
|
||||
## Currently, using other than the `AccountStateDB` ledgers are
|
||||
## experimental and test only. Eventually, the `GenesisLedgerRef` wrapper
|
||||
## should disappear so that the `Ledger` object (which encapsulates
|
||||
## `AccountsCache` and `AccountsLedger`) will prevail.
|
||||
## Exportable ledger DB just for initialising Genesis.
|
||||
##
|
||||
addAccount: GenesisAddAccountFn
|
||||
compensateLegacySetup: GenesisCompensateLegacySetupFn
|
||||
setStorage: GenesisSetStorageFn
|
||||
commit: GenesisCommitFn
|
||||
rootHash: GenesisRootHashFn
|
||||
getTrie: GenesisGetTrieFn
|
||||
|
||||
const
|
||||
GenesisLedgerTypeDefault* = LedgerType(0)
|
||||
## Default ledger type to use, `LedgerType(0)` uses `AccountStateDB`
|
||||
## rather than a `Ledger` variant.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc initStateDbledgerRef(db: CoreDbRef; pruneTrie: bool): GenesisLedgerRef =
|
||||
let sdb = newAccountStateDB(db, emptyRlpHash, pruneTrie)
|
||||
|
||||
GenesisLedgerRef(
|
||||
addAccount: proc(
|
||||
address: EthAddress;
|
||||
nonce: AccountNonce;
|
||||
balance: UInt256;
|
||||
code: openArray[byte];
|
||||
) {.catchRaise.} =
|
||||
sdb.setAccount(address, newAccount(nonce, balance))
|
||||
sdb.setCode(address, code),
|
||||
|
||||
compensateLegacySetup: proc() =
|
||||
if pruneTrie: db.compensateLegacySetup(),
|
||||
|
||||
setStorage: proc(
|
||||
address: EthAddress;
|
||||
slot: UInt256;
|
||||
val: UInt256;
|
||||
) {.rlpRaise.} =
|
||||
sdb.setStorage(address, slot, val),
|
||||
|
||||
commit: proc() =
|
||||
discard,
|
||||
|
||||
rootHash: proc(): Hash256 =
|
||||
sdb.rootHash(),
|
||||
|
||||
getTrie: proc(): CoreDbMptRef =
|
||||
sdb.getTrie())
|
||||
|
||||
|
||||
proc initAccountsLedgerRef(
|
||||
db: CoreDbRef;
|
||||
pruneTrie: bool;
|
||||
ledgerType: LedgerType;
|
||||
): GenesisLedgerRef =
|
||||
let ac = ledgerType.init(db, emptyRlpHash, pruneTrie)
|
||||
## Methods jump table
|
||||
let ac = LedgerCache.init(db, EMPTY_ROOT_HASH)
|
||||
|
||||
GenesisLedgerRef(
|
||||
addAccount: proc(
|
||||
|
@ -116,9 +66,6 @@ proc initAccountsLedgerRef(
|
|||
ac.setBalance(address, balance)
|
||||
ac.setCode(address, @code),
|
||||
|
||||
compensateLegacySetup: proc() =
|
||||
if pruneTrie: db.compensateLegacySetup(),
|
||||
|
||||
setStorage: proc(
|
||||
address: EthAddress;
|
||||
slot: UInt256;
|
||||
|
@ -141,15 +88,11 @@ proc initAccountsLedgerRef(
|
|||
|
||||
proc newStateDB*(
|
||||
db: CoreDbRef;
|
||||
pruneTrie: bool;
|
||||
ledgerType = LedgerType(0);
|
||||
ledgerType: LedgerType;
|
||||
): GenesisLedgerRef =
|
||||
## The flag `ledgerType` is set to zero for compatibility with legacy apps
|
||||
## (see `test_state_network`).
|
||||
if ledgerType != LedgerType(0):
|
||||
db.initAccountsLedgerRef(pruneTrie, ledgerType)
|
||||
else:
|
||||
db.initStateDbledgerRef pruneTrie
|
||||
## Currently only `LedgerCache` supported for `ledgerType`.
|
||||
doAssert ledgerType == LedgerCache
|
||||
db.initAccountsLedgerRef()
|
||||
|
||||
proc getTrie*(sdb: GenesisLedgerRef): CoreDbMptRef =
|
||||
## Getter, used in `test_state_network`
|
||||
|
@ -167,22 +110,9 @@ proc toGenesisHeader*(
|
|||
## The function returns the `Genesis` block header.
|
||||
##
|
||||
|
||||
# The following kludge is needed for the `LegacyDbPersistent` type database
|
||||
# when `pruneTrie` is enabled. For other cases, this code is irrelevant.
|
||||
sdb.compensateLegacySetup()
|
||||
|
||||
for address, account in g.alloc:
|
||||
sdb.addAccount(address, account.nonce, account.balance, account.code)
|
||||
|
||||
# Kludge:
|
||||
#
|
||||
# See https://github.com/status-im/nim-eth/issues/9 where other,
|
||||
# probably related debilities are discussed.
|
||||
#
|
||||
# This kludge also fixes the initial crash described in
|
||||
# https://github.com/status-im/nimbus-eth1/issues/932.
|
||||
sdb.compensateLegacySetup() # <-- kludge
|
||||
|
||||
for k, v in account.storage:
|
||||
sdb.setStorage(address, k, v)
|
||||
|
||||
|
@ -226,20 +156,20 @@ proc toGenesisHeader*(
|
|||
genesis: Genesis;
|
||||
fork: HardFork;
|
||||
db = CoreDbRef(nil);
|
||||
ledgerType = GenesisLedgerTypeDefault;
|
||||
ledgerType = LedgerCache;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
## Generate the genesis block header from the `genesis` and `config`
|
||||
## argument value.
|
||||
let
|
||||
db = if db.isNil: newCoreDbRef LegacyDbMemory else: db
|
||||
sdb = newStateDB(db, pruneTrie = true, ledgerType)
|
||||
db = if db.isNil: AristoDbMemory.newCoreDbRef() else: db
|
||||
sdb = db.newStateDB(ledgerType)
|
||||
toGenesisHeader(genesis, sdb, fork)
|
||||
|
||||
proc toGenesisHeader*(
|
||||
params: NetworkParams;
|
||||
db = CoreDbRef(nil);
|
||||
ledgerType = GenesisLedgerTypeDefault;
|
||||
ledgerType = LedgerCache;
|
||||
): BlockHeader
|
||||
{.raises: [CatchableError].} =
|
||||
## Generate the genesis block header from the `genesis` and `config`
|
||||
|
|
|
@ -106,9 +106,8 @@ const sharedLibText = if defined(linux): " (*.so, *.so.N)"
|
|||
|
||||
type
|
||||
ChainDbMode* {.pure.} = enum
|
||||
Prune
|
||||
Archive
|
||||
Aristo
|
||||
AriPrune
|
||||
|
||||
NimbusCmd* {.pure.} = enum
|
||||
noCommand
|
||||
|
@ -117,7 +116,7 @@ type
|
|||
ProtocolFlag* {.pure.} = enum
|
||||
## Protocol flags
|
||||
Eth ## enable eth subprotocol
|
||||
Snap ## enable snap sub-protocol
|
||||
#Snap ## enable snap sub-protocol
|
||||
Les ## enable les subprotocol
|
||||
|
||||
RpcFlag* {.pure.} = enum
|
||||
|
@ -134,7 +133,7 @@ type
|
|||
SyncMode* {.pure.} = enum
|
||||
Default
|
||||
Full ## Beware, experimental
|
||||
Snap ## Beware, experimental
|
||||
#Snap ## Beware, experimental
|
||||
Stateless ## Beware, experimental
|
||||
|
||||
NimbusConf* = object of RootObj
|
||||
|
@ -158,12 +157,11 @@ type
|
|||
chainDbMode* {.
|
||||
desc: "Blockchain database"
|
||||
longDesc:
|
||||
"- Prune -- Legacy/reference database, full pruning\n" &
|
||||
"- Archive -- Legacy/reference database without pruning\n" &
|
||||
"- Aristo -- Experimental single state DB\n" &
|
||||
"- Aristo -- Single state DB, full node\n" &
|
||||
"- AriPrune -- Aristo with curbed block history (for testing)\n" &
|
||||
""
|
||||
defaultValue: ChainDbMode.Prune
|
||||
defaultValueDesc: $ChainDbMode.Prune
|
||||
defaultValue: ChainDbMode.Aristo
|
||||
defaultValueDesc: $ChainDbMode.Aristo
|
||||
abbr : "p"
|
||||
name: "chaindb" }: ChainDbMode
|
||||
|
||||
|
@ -172,7 +170,7 @@ type
|
|||
longDesc:
|
||||
"- default -- legacy sync mode\n" &
|
||||
"- full -- full blockchain archive\n" &
|
||||
"- snap -- experimental snap mode (development only)\n" &
|
||||
# "- snap -- experimental snap mode (development only)\n" &
|
||||
"- stateless -- experimental stateless mode (development only)"
|
||||
defaultValue: SyncMode.Default
|
||||
defaultValueDesc: $SyncMode.Default
|
||||
|
@ -376,7 +374,8 @@ type
|
|||
|
||||
protocols {.
|
||||
desc: "Enable specific set of server protocols (available: Eth, " &
|
||||
" Snap, Les, None.) This will not affect the sync mode"
|
||||
" Les, None.) This will not affect the sync mode"
|
||||
# " Snap, Les, None.) This will not affect the sync mode"
|
||||
defaultValue: @[]
|
||||
defaultValueDesc: $ProtocolFlag.Eth
|
||||
name: "protocols" .}: seq[string]
|
||||
|
@ -643,7 +642,7 @@ proc getProtocolFlags*(conf: NimbusConf): set[ProtocolFlag] =
|
|||
case item.toLowerAscii()
|
||||
of "eth": result.incl ProtocolFlag.Eth
|
||||
of "les": result.incl ProtocolFlag.Les
|
||||
of "snap": result.incl ProtocolFlag.Snap
|
||||
# of "snap": result.incl ProtocolFlag.Snap
|
||||
of "none": noneOk = true
|
||||
else:
|
||||
error "Unknown protocol", name=item
|
||||
|
|
|
@ -23,10 +23,6 @@ proc importRlpBlock*(blocksRlp: openArray[byte]; com: CommonRef; importFile: str
|
|||
header: BlockHeader
|
||||
body: BlockBody
|
||||
|
||||
# The following kludge is needed for the `LegacyDbPersistent` type database
|
||||
# when `pruneTrie` is enabled. For other cases, this code is irrelevant.
|
||||
com.db.compensateLegacySetup()
|
||||
|
||||
# even though the new imported blocks have block number
|
||||
# smaller than head, we keep importing it.
|
||||
# it maybe a side chain.
|
||||
|
|
|
@ -85,9 +85,6 @@ proc persistBlocksImpl(c: ChainRef; headers: openArray[BlockHeader];
|
|||
let vmState = c.getVmState(headers[0]).valueOr:
|
||||
return ValidationResult.Error
|
||||
|
||||
# Check point
|
||||
let stateRootChpt = vmState.parent.stateRoot
|
||||
|
||||
# Needed for figuring out whether KVT cleanup is due (see at the end)
|
||||
let (fromBlock, toBlock) = (headers[0].blockNumber, headers[^1].blockNumber)
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ proc update(dh: TxChainRef; parent: BlockHeader)
|
|||
let
|
||||
timestamp = dh.getTimestamp(parent)
|
||||
db = dh.com.db
|
||||
acc = dh.com.ledgerType.init(db, parent.stateRoot, dh.com.pruneTrie)
|
||||
acc = dh.com.ledgerType.init(db, parent.stateRoot)
|
||||
fee = if dh.com.isLondon(parent.blockNumber + 1, timestamp):
|
||||
some(dh.com.baseFeeGet(parent).uint64.u256)
|
||||
else:
|
||||
|
|
|
@ -175,7 +175,7 @@ proc vmExecInit(xp: TxPoolRef): Result[TxPackerStateRef, string]
|
|||
|
||||
let packer = TxPackerStateRef( # return value
|
||||
xp: xp,
|
||||
tr: newCoreDbRef(LegacyDbMemory).mptPrune,
|
||||
tr: AristoDbMemory.newCoreDbRef().mptPrune,
|
||||
balance: xp.chain.vmState.readOnlyStateDB.getBalance(xp.chain.feeRecipient),
|
||||
numBlobPerBlock: 0,
|
||||
)
|
||||
|
|
|
@ -145,7 +145,6 @@ proc findTx*(
|
|||
|
||||
else:
|
||||
# Find `(vid,key)` on transaction layers
|
||||
var n = 0
|
||||
for (n,tx,layer,error) in db.txRef.txFrameWalk:
|
||||
if error != AristoError(0):
|
||||
return err(error)
|
||||
|
|
|
@ -32,13 +32,7 @@ export
|
|||
# setting up DB agnostic unit/integration tests.
|
||||
#
|
||||
# Uncomment the below symbols in order to activate the `Aristo` database.
|
||||
#const DefaultDbMemory* = AristoDbMemory
|
||||
#const DefaultDbPersistent* = AristoDbRocks
|
||||
|
||||
# Catch undefined symbols and set them to the legacy database.
|
||||
when not declared(DefaultDbMemory):
|
||||
const DefaultDbMemory* = LegacyDbMemory
|
||||
when not declared(DefaultDbPersistent):
|
||||
const DefaultDbPersistent* = LegacyDbPersistent
|
||||
const DefaultDbMemory* = AristoDbMemory
|
||||
const DefaultDbPersistent* = AristoDbRocks
|
||||
|
||||
# End
|
||||
|
|
|
@ -1,587 +0,0 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or distributed except
|
||||
# according to those terms.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/tables,
|
||||
eth/[common, rlp, trie/db, trie/hexary],
|
||||
stew/byteutils,
|
||||
results,
|
||||
../../../errors,
|
||||
".."/[base, base/base_desc]
|
||||
|
||||
type
|
||||
LegacyApiRlpError* = object of CoreDbApiError
|
||||
## For re-routing exceptions in iterator closure
|
||||
|
||||
# -----------
|
||||
|
||||
LegacyDbRef* = ref object of CoreDbRef
|
||||
kvt: CoreDxKvtRef ## Cache, no need to rebuild methods descriptor
|
||||
tdb: TrieDatabaseRef ## Descriptor reference copy captured with closures
|
||||
top: LegacyCoreDxTxRef ## Top transaction (if any)
|
||||
ctx: LegacyCoreDbCtxRef ## Cache, there is only one context here
|
||||
level: int ## Debugging
|
||||
|
||||
LegacyDbClose* = proc() {.gcsafe, raises: [].}
|
||||
## Custom destructor
|
||||
|
||||
HexaryChildDbRef = ref object
|
||||
trie: HexaryTrie ## For closure descriptor for capturing
|
||||
when CoreDbEnableApiTracking:
|
||||
colType: CoreDbColType ## Current sub-trie
|
||||
address: Option[EthAddress] ## For storage tree debugging
|
||||
accPath: Blob ## For storage tree debugging
|
||||
|
||||
LegacyCoreDbCtxRef = ref object of CoreDbCtxRef
|
||||
## Context (there is only one context here)
|
||||
base: LegacyDbRef
|
||||
|
||||
LegacyCoreDxTxRef = ref object of CoreDxTxRef
|
||||
ltx: DbTransaction ## Legacy transaction descriptor
|
||||
back: LegacyCoreDxTxRef ## Previous transaction
|
||||
level: int ## Transaction level when positive
|
||||
|
||||
RecorderRef = ref object of RootRef
|
||||
flags: set[CoreDbCaptFlags]
|
||||
parent: TrieDatabaseRef
|
||||
logger: TableRef[Blob,Blob]
|
||||
appDb: LegacyDbRef
|
||||
|
||||
LegacyColRef* = ref object of CoreDbColRef
|
||||
root: Hash256 ## Hash key
|
||||
when CoreDbEnableApiTracking:
|
||||
colType: CoreDbColType ## Current sub-trie
|
||||
address: Option[EthAddress] ## For storage tree debugging
|
||||
accPath: Blob ## For storage tree debugging
|
||||
|
||||
LegacyCoreDbError = ref object of CoreDbErrorRef
|
||||
ctx: string ## Exception or error context info
|
||||
name: string ## name of exception
|
||||
msg: string ## Exception info
|
||||
|
||||
# ------------
|
||||
|
||||
LegacyCoreDbKvtBE = ref object of CoreDbKvtBackendRef
|
||||
tdb: TrieDatabaseRef
|
||||
|
||||
LegacyCoreDbMptBE = ref object of CoreDbMptBackendRef
|
||||
mpt: HexaryTrie
|
||||
|
||||
proc init*(
|
||||
db: LegacyDbRef;
|
||||
dbType: CoreDbType;
|
||||
tdb: TrieDatabaseRef;
|
||||
closeDb = LegacyDbClose(nil);
|
||||
): CoreDbRef
|
||||
{.gcsafe.}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private helpers, exception management
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
template mapRlpException(db: LegacyDbRef; info: static[string]; code: untyped) =
|
||||
try:
|
||||
code
|
||||
except RlpError as e:
|
||||
return err(db.bless(RlpException, LegacyCoreDbError(
|
||||
ctx: info,
|
||||
name: $e.name,
|
||||
msg: e.msg)))
|
||||
|
||||
template reraiseRlpException(info: static[string]; code: untyped) =
|
||||
try:
|
||||
code
|
||||
except RlpError as e:
|
||||
let msg = info & ", name=" & $e.name & ", msg=\"" & e.msg & "\""
|
||||
raise (ref LegacyApiRlpError)(msg: msg)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private helpers, other functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func errorPrint(e: CoreDbErrorRef): string =
|
||||
if not e.isNil:
|
||||
let e = e.LegacyCoreDbError
|
||||
result &= "ctx=" & $e.ctx
|
||||
if e.name != "":
|
||||
result &= ", name=\"" & $e.name & "\""
|
||||
if e.msg != "":
|
||||
result &= ", msg=\"" & $e.msg & "\""
|
||||
|
||||
func colPrint(col: CoreDbColRef): string =
|
||||
if not col.isNil:
|
||||
if not col.ready:
|
||||
result = "$?"
|
||||
else:
|
||||
var col = LegacyColRef(col)
|
||||
when CoreDbEnableApiTracking:
|
||||
result = "(" & $col.colType & ","
|
||||
if col.address.isSome:
|
||||
result &= "@"
|
||||
if col.accPath.len == 0:
|
||||
result &= "ø"
|
||||
else:
|
||||
result &= col.accPath.toHex & ","
|
||||
result &= "%" & col.address.unsafeGet.toHex & ","
|
||||
if col.root != EMPTY_ROOT_HASH:
|
||||
result &= "£" & col.root.data.toHex
|
||||
else:
|
||||
result &= "£ø"
|
||||
when CoreDbEnableApiTracking:
|
||||
result &= ")"
|
||||
|
||||
func txLevel(db: LegacyDbRef): int =
|
||||
if not db.top.isNil:
|
||||
return db.top.level
|
||||
|
||||
func lroot(col: CoreDbColRef): Hash256 =
|
||||
if not col.isNil and col.ready:
|
||||
return col.LegacyColRef.root
|
||||
EMPTY_ROOT_HASH
|
||||
|
||||
|
||||
proc toCoreDbAccount(
|
||||
db: LegacyDbRef;
|
||||
data: Blob;
|
||||
address: EthAddress;
|
||||
): CoreDbAccount
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
let acc = rlp.decode(data, Account)
|
||||
result = CoreDbAccount(
|
||||
address: address,
|
||||
nonce: acc.nonce,
|
||||
balance: acc.balance,
|
||||
codeHash: acc.codeHash)
|
||||
if acc.storageRoot != EMPTY_ROOT_HASH:
|
||||
result.storage = db.bless LegacyColRef(root: acc.storageRoot)
|
||||
when CoreDbEnableApiTracking:
|
||||
result.storage.LegacyColRef.colType = CtStorage # redundant, ord() = 0
|
||||
result.storage.LegacyColRef.address = some(address)
|
||||
result.storage.LegacyColRef.accPath = @(address.keccakHash.data)
|
||||
|
||||
|
||||
proc toAccount(
|
||||
acc: CoreDbAccount;
|
||||
): Account =
|
||||
## Fast rewrite of `recast()`
|
||||
Account(
|
||||
nonce: acc.nonce,
|
||||
balance: acc.balance,
|
||||
codeHash: acc.codeHash,
|
||||
storageRoot: acc.storage.lroot)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private mixin methods for `trieDB` (backport from capturedb/tracer sources)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc get(db: RecorderRef, key: openArray[byte]): Blob =
|
||||
## Mixin for `trieDB()`
|
||||
result = db.logger.getOrDefault @key
|
||||
if result.len == 0:
|
||||
result = db.parent.get(key)
|
||||
if result.len != 0:
|
||||
db.logger[@key] = result
|
||||
|
||||
proc put(db: RecorderRef, key, value: openArray[byte]) =
|
||||
## Mixin for `trieDB()`
|
||||
db.logger[@key] = @value
|
||||
if PersistPut in db.flags:
|
||||
db.parent.put(key, value)
|
||||
|
||||
proc contains(db: RecorderRef, key: openArray[byte]): bool =
|
||||
## Mixin for `trieDB()`
|
||||
if db.logger.hasKey @key:
|
||||
return true
|
||||
if db.parent.contains key:
|
||||
return true
|
||||
|
||||
proc del(db: RecorderRef, key: openArray[byte]) =
|
||||
## Mixin for `trieDB()`
|
||||
db.logger.del @key
|
||||
if PersistDel in db.flags:
|
||||
db.parent.del key
|
||||
|
||||
proc newRecorderRef(
|
||||
db: LegacyDbRef;
|
||||
flags: set[CoreDbCaptFlags];
|
||||
): RecorderRef =
|
||||
## Capture constuctor, uses `mixin` values from above
|
||||
result = RecorderRef(
|
||||
flags: flags,
|
||||
parent: db.tdb,
|
||||
logger: newTable[Blob,Blob]())
|
||||
let newDb = LegacyDbRef(
|
||||
level: db.level+1,
|
||||
trackLegaApi: db.trackLegaApi,
|
||||
trackNewApi: db.trackNewApi,
|
||||
trackLedgerApi: db.trackLedgerApi,
|
||||
localDbOnly: db.localDbOnly,
|
||||
profTab: db.profTab,
|
||||
ledgerHook: db.ledgerHook)
|
||||
# Note: the **mixin** magic happens in `trieDB()`
|
||||
result.appDb = newDb.init(db.dbType, trieDB result).LegacyDbRef
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private database method function tables
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc kvtMethods(db: LegacyDbRef): CoreDbKvtFns =
|
||||
## Key-value database table handlers
|
||||
let tdb = db.tdb
|
||||
CoreDbKvtFns(
|
||||
backendFn: proc(): CoreDbKvtBackendRef =
|
||||
db.bless(LegacyCoreDbKvtBE(tdb: tdb)),
|
||||
|
||||
getFn: proc(k: openArray[byte]): CoreDbRc[Blob] =
|
||||
let data = tdb.get(k)
|
||||
if 0 < data.len:
|
||||
return ok(data)
|
||||
err(db.bless(KvtNotFound, LegacyCoreDbError(ctx: "getFn()"))),
|
||||
|
||||
delFn: proc(k: openArray[byte]): CoreDbRc[void] =
|
||||
tdb.del(k)
|
||||
ok(),
|
||||
|
||||
putFn: proc(k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] =
|
||||
tdb.put(k,v)
|
||||
ok(),
|
||||
|
||||
hasKeyFn: proc(k: openArray[byte]): CoreDbRc[bool] =
|
||||
ok(tdb.contains(k)),
|
||||
|
||||
saveOffSiteFn: proc(): CoreDbRc[void] =
|
||||
# Emulate `Kvt` behaviour
|
||||
if 0 < db.txLevel():
|
||||
const info = "saveOffSiteFn()"
|
||||
return err(db.bless(TxPending, LegacyCoreDbError(ctx: info)))
|
||||
ok(),
|
||||
|
||||
forgetFn: proc(): CoreDbRc[void] =
|
||||
ok())
|
||||
|
||||
proc mptMethods(mpt: HexaryChildDbRef; db: LegacyDbRef): CoreDbMptFns =
|
||||
## Hexary trie database handlers
|
||||
CoreDbMptFns(
|
||||
backendFn: proc(): CoreDbMptBackendRef =
|
||||
db.bless(LegacyCoreDbMptBE(mpt: mpt.trie)),
|
||||
|
||||
fetchFn: proc(k: openArray[byte]): CoreDbRc[Blob] =
|
||||
db.mapRlpException("fetchFn()"):
|
||||
let data = mpt.trie.get(k)
|
||||
if 0 < data.len:
|
||||
return ok(data)
|
||||
err(db.bless(MptNotFound, LegacyCoreDbError(ctx: "fetchFn()"))),
|
||||
|
||||
deleteFn: proc(k: openArray[byte]): CoreDbRc[void] =
|
||||
db.mapRlpException("deleteFn()"):
|
||||
mpt.trie.del(k)
|
||||
ok(),
|
||||
|
||||
mergeFn: proc(k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] =
|
||||
db.mapRlpException("mergeFn()"):
|
||||
mpt.trie.put(k,v)
|
||||
ok(),
|
||||
|
||||
hasPathFn: proc(k: openArray[byte]): CoreDbRc[bool] =
|
||||
db.mapRlpException("hasPathFn()"):
|
||||
return ok(mpt.trie.contains(k)),
|
||||
|
||||
getColFn: proc(): CoreDbColRef =
|
||||
var col = LegacyColRef(root: mpt.trie.rootHash)
|
||||
when CoreDbEnableApiTracking:
|
||||
col.colType = mpt.colType
|
||||
col.address = mpt.address
|
||||
col.accPath = mpt.accPath
|
||||
db.bless(col),
|
||||
|
||||
isPruningFn: proc(): bool =
|
||||
mpt.trie.isPruning)
|
||||
|
||||
proc accMethods(mpt: HexaryChildDbRef; db: LegacyDbRef): CoreDbAccFns =
|
||||
## Hexary trie database handlers
|
||||
CoreDbAccFns(
|
||||
getMptFn: proc(): CoreDbRc[CoreDxMptRef] =
|
||||
let xMpt = HexaryChildDbRef(trie: mpt.trie)
|
||||
ok(db.bless CoreDxMptRef(methods: xMpt.mptMethods db)),
|
||||
|
||||
fetchFn: proc(k: EthAddress): CoreDbRc[CoreDbAccount] =
|
||||
db.mapRlpException "fetchFn()":
|
||||
let data = mpt.trie.get(k.keccakHash.data)
|
||||
if 0 < data.len:
|
||||
return ok db.toCoreDbAccount(data,k)
|
||||
err(db.bless(AccNotFound, LegacyCoreDbError(ctx: "fetchFn()"))),
|
||||
|
||||
deleteFn: proc(k: EthAddress): CoreDbRc[void] =
|
||||
db.mapRlpException("deleteFn()"):
|
||||
mpt.trie.del(k.keccakHash.data)
|
||||
ok(),
|
||||
|
||||
stoFlushFn: proc(k: EthAddress): CoreDbRc[void] =
|
||||
ok(),
|
||||
|
||||
mergeFn: proc(v: CoreDbAccount): CoreDbRc[void] =
|
||||
db.mapRlpException("mergeFn()"):
|
||||
mpt.trie.put(v.address.keccakHash.data, rlp.encode v.toAccount)
|
||||
ok(),
|
||||
|
||||
hasPathFn: proc(k: EthAddress): CoreDbRc[bool] =
|
||||
db.mapRlpException("hasPath()"):
|
||||
return ok(mpt.trie.contains k.keccakHash.data),
|
||||
|
||||
getColFn: proc(): CoreDbColRef =
|
||||
var col = LegacyColRef(root: mpt.trie.rootHash)
|
||||
when CoreDbEnableApiTracking:
|
||||
col.colType = mpt.colType
|
||||
col.address = mpt.address
|
||||
col.accPath = mpt.accPath
|
||||
db.bless(col),
|
||||
|
||||
isPruningFn: proc(): bool =
|
||||
mpt.trie.isPruning)
|
||||
|
||||
|
||||
proc ctxMethods(ctx: LegacyCoreDbCtxRef): CoreDbCtxFns =
|
||||
let
|
||||
db = ctx.base
|
||||
tdb = db.tdb
|
||||
|
||||
CoreDbCtxFns(
|
||||
newColFn: proc(
|
||||
colType: CoreDbColType;
|
||||
root: Hash256;
|
||||
address: Option[EthAddress];
|
||||
): CoreDbRc[CoreDbColRef] =
|
||||
var col = LegacyColRef(root: root)
|
||||
when CoreDbEnableApiTracking:
|
||||
col.colType = colType
|
||||
col.address = address
|
||||
if address.isSome:
|
||||
col.accPath = @(address.unsafeGet.keccakHash.data)
|
||||
ok(db.bless col),
|
||||
|
||||
getMptFn: proc(col: CoreDbColRef, prune: bool): CoreDbRc[CoreDxMptRef] =
|
||||
var mpt = HexaryChildDbRef(trie: initHexaryTrie(tdb, col.lroot, prune))
|
||||
when CoreDbEnableApiTracking:
|
||||
if not col.isNil and col.ready:
|
||||
let col = col.LegacyColRef
|
||||
mpt.colType = col.colType
|
||||
mpt.address = col.address
|
||||
mpt.accPath = col.accPath
|
||||
ok(db.bless CoreDxMptRef(methods: mpt.mptMethods db)),
|
||||
|
||||
getAccFn: proc(col: CoreDbColRef, prune: bool): CoreDbRc[CoreDxAccRef] =
|
||||
var mpt = HexaryChildDbRef(trie: initHexaryTrie(tdb, col.lroot, prune))
|
||||
when CoreDbEnableApiTracking:
|
||||
if not col.isNil and col.ready:
|
||||
if col.LegacyColRef.colType != CtAccounts:
|
||||
let ctx = LegacyCoreDbError(
|
||||
ctx: "newAccFn()",
|
||||
msg: "got " & $col.LegacyColRef.colType)
|
||||
return err(db.bless(RootUnacceptable, ctx))
|
||||
mpt.colType = CtAccounts
|
||||
ok(db.bless CoreDxAccRef(methods: mpt.accMethods db)),
|
||||
|
||||
forgetFn: proc() =
|
||||
discard)
|
||||
|
||||
|
||||
proc txMethods(tx: CoreDxTxRef): CoreDbTxFns =
|
||||
let tx = tx.LegacyCoreDxTxRef
|
||||
|
||||
proc pop(tx: LegacyCoreDxTxRef) =
|
||||
if 0 < tx.level:
|
||||
tx.parent.LegacyDbRef.top = tx.back
|
||||
tx.back = LegacyCoreDxTxRef(nil)
|
||||
tx.level = -1
|
||||
|
||||
CoreDbTxFns(
|
||||
levelFn: proc(): int =
|
||||
tx.level,
|
||||
|
||||
commitFn: proc(applyDeletes: bool): CoreDbRc[void] =
|
||||
tx.ltx.commit(applyDeletes)
|
||||
tx.pop()
|
||||
ok(),
|
||||
|
||||
rollbackFn: proc(): CoreDbRc[void] =
|
||||
tx.ltx.rollback()
|
||||
tx.pop()
|
||||
ok(),
|
||||
|
||||
disposeFn: proc(): CoreDbRc[void] =
|
||||
tx.ltx.dispose()
|
||||
tx.pop()
|
||||
ok(),
|
||||
|
||||
safeDisposeFn: proc(): CoreDbRc[void] =
|
||||
tx.ltx.safeDispose()
|
||||
tx.pop()
|
||||
ok())
|
||||
|
||||
proc cptMethods(cpt: RecorderRef; db: LegacyDbRef): CoreDbCaptFns =
|
||||
CoreDbCaptFns(
|
||||
recorderFn: proc(): CoreDbRef =
|
||||
cpt.appDb,
|
||||
|
||||
logDbFn: proc(): TableRef[Blob,Blob] =
|
||||
cpt.logger,
|
||||
|
||||
getFlagsFn: proc(): set[CoreDbCaptFlags] =
|
||||
cpt.flags,
|
||||
|
||||
forgetFn: proc() =
|
||||
discard)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private base methods (including constructors)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc baseMethods(
|
||||
db: LegacyDbRef;
|
||||
dbType: CoreDbType;
|
||||
closeDb: LegacyDbClose;
|
||||
): CoreDbBaseFns =
|
||||
let db = db
|
||||
CoreDbBaseFns(
|
||||
levelFn: proc(): int =
|
||||
db.txLevel(),
|
||||
|
||||
destroyFn: proc(ignore: bool) =
|
||||
if not closeDb.isNil:
|
||||
closeDb(),
|
||||
|
||||
colStateFn: proc(col: CoreDbColRef): CoreDbRc[Hash256] =
|
||||
ok(col.lroot),
|
||||
|
||||
colPrintFn: proc(col: CoreDbColRef): string =
|
||||
col.colPrint(),
|
||||
|
||||
errorPrintFn: proc(e: CoreDbErrorRef): string =
|
||||
e.errorPrint(),
|
||||
|
||||
legacySetupFn: proc() =
|
||||
db.tdb.put(EMPTY_ROOT_HASH.data, @[0x80u8]),
|
||||
|
||||
newKvtFn: proc(sharedTable = true): CoreDbRc[CoreDxKvtRef] =
|
||||
ok(db.kvt),
|
||||
|
||||
newCtxFn: proc(): CoreDbCtxRef =
|
||||
db.ctx,
|
||||
|
||||
swapCtxFn: proc(ctx: CoreDbCtxRef): CoreDbCtxRef =
|
||||
doAssert CoreDbCtxRef(db.ctx) == ctx
|
||||
ctx,
|
||||
|
||||
newCtxFromTxFn: proc(
|
||||
root: Hash256;
|
||||
colType: CoreDbColType;
|
||||
): CoreDbRc[CoreDbCtxRef] =
|
||||
ok(db.ctx),
|
||||
|
||||
beginFn: proc(): CoreDbRc[CoreDxTxRef] =
|
||||
db.top = LegacyCoreDxTxRef(
|
||||
ltx: db.tdb.beginTransaction,
|
||||
level: (if db.top.isNil: 1 else: db.top.level + 1),
|
||||
back: db.top)
|
||||
db.top.methods = db.top.txMethods()
|
||||
ok(db.bless db.top),
|
||||
|
||||
newCaptureFn: proc(flgs: set[CoreDbCaptFlags]): CoreDbRc[CoreDxCaptRef] =
|
||||
let fns = db.newRecorderRef(flgs).cptMethods(db)
|
||||
ok(db.bless CoreDxCaptRef(methods: fns)),
|
||||
|
||||
persistentFn: proc(bn: Option[BlockNumber]): CoreDbRc[void] =
|
||||
# Emulate `Aristo` behaviour
|
||||
if 0 < db.txLevel():
|
||||
const info = "persistentFn()"
|
||||
return err(db.bless(TxPending, LegacyCoreDbError(ctx: info)))
|
||||
ok())
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public constructor helpers
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc init*(
|
||||
db: LegacyDbRef;
|
||||
dbType: CoreDbType;
|
||||
tdb: TrieDatabaseRef;
|
||||
closeDb = LegacyDbClose(nil);
|
||||
): CoreDbRef =
|
||||
## Constructor helper
|
||||
|
||||
# Local extensions
|
||||
db.tdb = tdb
|
||||
db.kvt = db.bless CoreDxKvtRef(methods: db.kvtMethods())
|
||||
|
||||
# Base descriptor
|
||||
db.dbType = dbType
|
||||
db.methods = db.baseMethods(dbType, closeDb)
|
||||
|
||||
# Blind context layer
|
||||
let ctx = LegacyCoreDbCtxRef(base: db)
|
||||
ctx.methods = ctx.ctxMethods
|
||||
db.ctx = db.bless ctx
|
||||
|
||||
db.bless
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public constructor and low level data retrieval, storage & transation frame
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc newLegacyPersistentCoreDbRef*(db: TrieDatabaseRef): CoreDbRef =
|
||||
LegacyDbRef().init(LegacyDbPersistent, db)
|
||||
|
||||
proc newLegacyMemoryCoreDbRef*(): CoreDbRef =
|
||||
LegacyDbRef().init(LegacyDbMemory, newMemoryDB())
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public legacy helpers
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func isLegacy*(be: CoreDbRef): bool =
|
||||
be.dbType in {LegacyDbMemory, LegacyDbPersistent}
|
||||
|
||||
func toLegacy*(be: CoreDbKvtBackendRef): TrieDatabaseRef =
|
||||
if be.parent.isLegacy:
|
||||
return be.LegacyCoreDbKvtBE.tdb
|
||||
|
||||
func toLegacy*(be: CoreDbMptBackendRef): HexaryTrie =
|
||||
if be.parent.isLegacy:
|
||||
return be.LegacyCoreDbMptBE.mpt
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public legacy iterators
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
iterator legaKvtPairs*(kvt: CoreDxKvtRef): (Blob, Blob) =
|
||||
for k,v in kvt.parent.LegacyDbRef.tdb.pairsInMemoryDB:
|
||||
yield (k,v)
|
||||
|
||||
iterator legaMptPairs*(
|
||||
mpt: CoreDxMptRef;
|
||||
): (Blob,Blob)
|
||||
{.gcsafe, raises: [LegacyApiRlpError].} =
|
||||
reraiseRlpException("legaMptPairs()"):
|
||||
for k,v in mpt.methods.backendFn().LegacyCoreDbMptBE.mpt.pairs():
|
||||
yield (k,v)
|
||||
|
||||
iterator legaReplicate*(
|
||||
mpt: CoreDxMptRef;
|
||||
): (Blob,Blob)
|
||||
{.gcsafe, raises: [LegacyApiRlpError].} =
|
||||
reraiseRlpException("legaReplicate()"):
|
||||
for k,v in mpt.methods.backendFn().LegacyCoreDbMptBE.mpt.replicate():
|
||||
yield (k,v)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
|
@ -1,79 +0,0 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or distributed except
|
||||
# according to those terms.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
eth/trie/db,
|
||||
eth/db/kvstore,
|
||||
rocksdb,
|
||||
../base,
|
||||
./legacy_db,
|
||||
../../kvstore_rocksdb
|
||||
|
||||
type
|
||||
LegaPersDbRef = ref object of LegacyDbRef
|
||||
rdb: RocksStoreRef # for backend access with legacy mode
|
||||
|
||||
ChainDB = ref object of RootObj
|
||||
kv: KvStoreRef
|
||||
rdb: RocksStoreRef
|
||||
|
||||
# TODO KvStore is a virtual interface and TrieDB is a virtual interface - one
|
||||
# will be enough eventually - unless the TrieDB interface gains operations
|
||||
# that are not typical to KvStores
|
||||
proc get(db: ChainDB, key: openArray[byte]): seq[byte] =
|
||||
var res: seq[byte]
|
||||
proc onData(data: openArray[byte]) = res = @data
|
||||
if db.kv.get(key, onData).expect("working database"):
|
||||
return res
|
||||
|
||||
proc put(db: ChainDB, key, value: openArray[byte]) =
|
||||
db.kv.put(key, value).expect("working database")
|
||||
|
||||
proc contains(db: ChainDB, key: openArray[byte]): bool =
|
||||
db.kv.contains(key).expect("working database")
|
||||
|
||||
proc del(db: ChainDB, key: openArray[byte]): bool =
|
||||
db.kv.del(key).expect("working database")
|
||||
|
||||
proc newChainDB(path: string): KvResult[ChainDB] =
|
||||
let rdb = RocksStoreRef.init(path, "nimbus").valueOr:
|
||||
return err(error)
|
||||
ok(ChainDB(kv: kvStore rdb, rdb: rdb))
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public constructor and low level data retrieval, storage & transation frame
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc newLegacyPersistentCoreDbRef*(path: string): CoreDbRef =
|
||||
# when running `newChainDB(path)`. converted to a `Defect`.
|
||||
let backend = newChainDB(path).valueOr:
|
||||
let msg = "DB initialisation : " & error
|
||||
raise (ref ResultDefect)(msg: msg)
|
||||
|
||||
proc done() =
|
||||
backend.rdb.close()
|
||||
|
||||
LegaPersDbRef(rdb: backend.rdb).init(LegacyDbPersistent, backend.trieDB, done)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public helper for direct backend access
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc toRocksStoreRef*(
|
||||
db: CoreDbKvtBackendRef | CoreDbMptBackendRef
|
||||
): RocksStoreRef =
|
||||
if db.parent.dbType == LegacyDbPersistent:
|
||||
return LegaPersDbRef(db.parent).rdb
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
|
@ -26,14 +26,12 @@ from ../../aristo
|
|||
type
|
||||
CoreDbType* = enum
|
||||
Ooops
|
||||
LegacyDbMemory
|
||||
LegacyDbPersistent
|
||||
AristoDbMemory ## Memory backend emulator
|
||||
AristoDbRocks ## RocksDB backend
|
||||
AristoDbVoid ## No backend
|
||||
|
||||
const
|
||||
CoreDbPersistentTypes* = {LegacyDbPersistent, AristoDbRocks}
|
||||
CoreDbPersistentTypes* = {AristoDbRocks}
|
||||
|
||||
type
|
||||
CoreDbKvtRef* = distinct CoreDxKvtRef # Legacy descriptor
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
import
|
||||
std/typetraits,
|
||||
eth/common,
|
||||
./backend/[aristo_db, legacy_db],
|
||||
./backend/aristo_db,
|
||||
./base/[api_tracking, base_desc],
|
||||
./base
|
||||
|
||||
|
@ -41,9 +41,6 @@ iterator pairs*(kvt: CoreDxKvtRef): (Blob, Blob) {.apiRaise.} =
|
|||
##
|
||||
kvt.setTrackNewApi KvtPairsIt
|
||||
case kvt.parent.dbType:
|
||||
of LegacyDbMemory:
|
||||
for k,v in kvt.legaKvtPairs():
|
||||
yield (k,v)
|
||||
of AristoDbMemory:
|
||||
for k,v in kvt.aristoKvtPairsMem():
|
||||
yield (k,v)
|
||||
|
@ -54,14 +51,11 @@ iterator pairs*(kvt: CoreDxKvtRef): (Blob, Blob) {.apiRaise.} =
|
|||
raiseAssert: "Unsupported database type: " & $kvt.parent.dbType
|
||||
kvt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
||||
|
||||
iterator pairs*(mpt: CoreDxMptRef): (Blob, Blob) {.apiRaise.} =
|
||||
iterator pairs*(mpt: CoreDxMptRef): (Blob, Blob) =
|
||||
## Trie traversal, only supported for `CoreDxMptRef` (not `Phk`)
|
||||
##
|
||||
mpt.setTrackNewApi MptPairsIt
|
||||
case mpt.parent.dbType:
|
||||
of LegacyDbMemory, LegacyDbPersistent:
|
||||
for k,v in mpt.legaMptPairs():
|
||||
yield (k,v)
|
||||
of AristoDbMemory, AristoDbRocks, AristoDbVoid:
|
||||
for k,v in mpt.aristoMptPairs():
|
||||
yield (k,v)
|
||||
|
@ -76,9 +70,6 @@ iterator replicate*(mpt: CoreDxMptRef): (Blob, Blob) {.apiRaise.} =
|
|||
##
|
||||
mpt.setTrackNewApi MptReplicateIt
|
||||
case mpt.parent.dbType:
|
||||
of LegacyDbMemory, LegacyDbPersistent:
|
||||
for k,v in mpt.legaReplicate():
|
||||
yield (k,v)
|
||||
of AristoDbMemory:
|
||||
for k,v in aristoReplicateMem(mpt):
|
||||
yield (k,v)
|
||||
|
@ -98,7 +89,7 @@ when ProvideLegacyAPI:
|
|||
for k,v in kvt.distinctBase.pairs(): yield (k,v)
|
||||
kvt.ifTrackLegaApi: debug legaApiTxt, api, elapsed
|
||||
|
||||
iterator pairs*(mpt: CoreDbMptRef): (Blob, Blob) {.apiRaise.} =
|
||||
iterator pairs*(mpt: CoreDbMptRef): (Blob, Blob) =
|
||||
## Trie traversal, not supported for `CoreDbPhkRef`
|
||||
mpt.setTrackLegaApi LegaMptPairsIt
|
||||
for k,v in mpt.distinctBase.pairs(): yield (k,v)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
import
|
||||
std/typetraits,
|
||||
eth/common,
|
||||
./backend/[aristo_db, aristo_rocksdb, legacy_db],
|
||||
./backend/[aristo_db, aristo_rocksdb],
|
||||
./base/[api_tracking, base_desc],
|
||||
./base
|
||||
|
||||
|
@ -30,7 +30,7 @@ when ProvideLegacyAPI and CoreDbEnableApiTracking:
|
|||
newApiTxt = logTxt & "API"
|
||||
|
||||
# Annotation helper(s)
|
||||
{.pragma: rlpRaise, gcsafe, raises: [AristoApiRlpError, LegacyApiRlpError].}
|
||||
{.pragma: rlpRaise, gcsafe, raises: [AristoApiRlpError].}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public iterators
|
||||
|
@ -41,9 +41,6 @@ iterator replicatePersistent*(mpt: CoreDxMptRef): (Blob, Blob) {.rlpRaise.} =
|
|||
##
|
||||
mpt.setTrackNewApi MptReplicateIt
|
||||
case mpt.parent.dbType:
|
||||
of LegacyDbMemory, LegacyDbPersistent:
|
||||
for k,v in mpt.legaReplicate():
|
||||
yield (k,v)
|
||||
of AristoDbMemory:
|
||||
for k,v in aristoReplicateMem(mpt):
|
||||
yield (k,v)
|
||||
|
|
|
@ -1,745 +0,0 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or distributed except
|
||||
# according to those terms.
|
||||
|
||||
## This file was renamed from `core_apps.nim`.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/[algorithm, options, sequtils],
|
||||
chronicles,
|
||||
eth/[common, rlp],
|
||||
stew/byteutils,
|
||||
"../.."/[errors, constants],
|
||||
../storage_types,
|
||||
"."/base
|
||||
|
||||
logScope:
|
||||
topics = "core_db-apps"
|
||||
|
||||
type
|
||||
TransactionKey = tuple
|
||||
blockNumber: BlockNumber
|
||||
index: int
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Forward declarations
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
output: var BlockHeader;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].}
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef,
|
||||
blockHash: Hash256;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [BlockNotFound].}
|
||||
|
||||
proc getBlockHash*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
output: var Hash256;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].}
|
||||
|
||||
proc addBlockNumberToHashLookup*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
) {.gcsafe.}
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef;
|
||||
blockHash: Hash256;
|
||||
output: var BlockHeader;
|
||||
): bool
|
||||
{.gcsafe.}
|
||||
|
||||
# Copied from `utils/utils` which cannot be imported here in order to
|
||||
# avoid circular imports.
|
||||
func hash(b: BlockHeader): Hash256
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private iterators
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
iterator findNewAncestors(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
## Returns the chain leading up from the given header until the first
|
||||
## ancestor it has in common with our canonical chain.
|
||||
var h = header
|
||||
var orig: BlockHeader
|
||||
while true:
|
||||
if db.getBlockHeader(h.blockNumber, orig) and orig.hash == h.hash:
|
||||
break
|
||||
|
||||
yield h
|
||||
|
||||
if h.parentHash == GENESIS_PARENT_HASH:
|
||||
break
|
||||
else:
|
||||
h = db.getBlockHeader(h.parentHash)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public iterators
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
iterator getBlockTransactionData*(
|
||||
db: CoreDbRef;
|
||||
transactionRoot: Hash256;
|
||||
): seq[byte]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var transactionDb = db.mptPrune transactionRoot
|
||||
var transactionIdx = 0
|
||||
while true:
|
||||
let transactionKey = rlp.encode(transactionIdx)
|
||||
if transactionKey in transactionDb:
|
||||
yield transactionDb.get(transactionKey)
|
||||
else:
|
||||
break
|
||||
inc transactionIdx
|
||||
|
||||
iterator getBlockTransactions*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
): Transaction
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
for encodedTx in db.getBlockTransactionData(header.txRoot):
|
||||
yield rlp.decode(encodedTx, Transaction)
|
||||
|
||||
iterator getBlockTransactionHashes*(
|
||||
db: CoreDbRef;
|
||||
blockHeader: BlockHeader;
|
||||
): Hash256
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
## Returns an iterable of the transaction hashes from th block specified
|
||||
## by the given block header.
|
||||
for encodedTx in db.getBlockTransactionData(blockHeader.txRoot):
|
||||
let tx = rlp.decode(encodedTx, Transaction)
|
||||
yield rlpHash(tx) # beware EIP-4844
|
||||
|
||||
iterator getWithdrawalsData*(
|
||||
db: CoreDbRef;
|
||||
withdrawalsRoot: Hash256;
|
||||
): seq[byte]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var wddb = db.mptPrune withdrawalsRoot
|
||||
var idx = 0
|
||||
while true:
|
||||
let wdKey = rlp.encode(idx)
|
||||
if wdKey in wddb:
|
||||
yield wddb.get(wdKey)
|
||||
else:
|
||||
break
|
||||
inc idx
|
||||
|
||||
iterator getReceipts*(
|
||||
db: CoreDbRef;
|
||||
receiptRoot: Hash256;
|
||||
): Receipt
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var receiptDb = db.mptPrune receiptRoot
|
||||
var receiptIdx = 0
|
||||
while true:
|
||||
let receiptKey = rlp.encode(receiptIdx)
|
||||
if receiptKey in receiptDb:
|
||||
let receiptData = receiptDb.get(receiptKey)
|
||||
yield rlp.decode(receiptData, Receipt)
|
||||
else:
|
||||
break
|
||||
inc receiptIdx
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private helpers
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func hash(b: BlockHeader): Hash256 =
|
||||
rlpHash(b)
|
||||
|
||||
proc removeTransactionFromCanonicalChain(
|
||||
db: CoreDbRef;
|
||||
transactionHash: Hash256;
|
||||
) =
|
||||
## Removes the transaction specified by the given hash from the canonical
|
||||
## chain.
|
||||
db.kvt.del(transactionHashToBlockKey(transactionHash).toOpenArray)
|
||||
|
||||
proc setAsCanonicalChainHead(
|
||||
db: CoreDbRef;
|
||||
headerHash: Hash256;
|
||||
): seq[BlockHeader]
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
## Sets the header as the canonical chain HEAD.
|
||||
let header = db.getBlockHeader(headerHash)
|
||||
|
||||
var newCanonicalHeaders = sequtils.toSeq(db.findNewAncestors(header))
|
||||
reverse(newCanonicalHeaders)
|
||||
for h in newCanonicalHeaders:
|
||||
var oldHash: Hash256
|
||||
if not db.getBlockHash(h.blockNumber, oldHash):
|
||||
break
|
||||
|
||||
let oldHeader = db.getBlockHeader(oldHash)
|
||||
for txHash in db.getBlockTransactionHashes(oldHeader):
|
||||
db.removeTransactionFromCanonicalChain(txHash)
|
||||
# TODO re-add txn to internal pending pool (only if local sender)
|
||||
|
||||
for h in newCanonicalHeaders:
|
||||
db.addBlockNumberToHashLookup(h)
|
||||
|
||||
db.kvt.put(canonicalHeadHashKey().toOpenArray, rlp.encode(headerHash))
|
||||
|
||||
return newCanonicalHeaders
|
||||
|
||||
proc markCanonicalChain(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
headerHash: Hash256;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
## mark this chain as canonical by adding block number to hash lookup
|
||||
## down to forking point
|
||||
var
|
||||
currHash = headerHash
|
||||
currHeader = header
|
||||
|
||||
# mark current header as canonical
|
||||
let key = blockNumberToHashKey(currHeader.blockNumber)
|
||||
db.kvt.put(key.toOpenArray, rlp.encode(currHash))
|
||||
|
||||
# it is a genesis block, done
|
||||
if currHeader.parentHash == Hash256():
|
||||
return true
|
||||
|
||||
# mark ancestor blocks as canonical too
|
||||
currHash = currHeader.parentHash
|
||||
if not db.getBlockHeader(currHeader.parentHash, currHeader):
|
||||
return false
|
||||
|
||||
while currHash != Hash256():
|
||||
let key = blockNumberToHashKey(currHeader.blockNumber)
|
||||
let data = db.kvt.get(key.toOpenArray)
|
||||
if data.len == 0:
|
||||
# not marked, mark it
|
||||
db.kvt.put(key.toOpenArray, rlp.encode(currHash))
|
||||
elif rlp.decode(data, Hash256) != currHash:
|
||||
# replace prev chain
|
||||
db.kvt.put(key.toOpenArray, rlp.encode(currHash))
|
||||
else:
|
||||
# forking point, done
|
||||
break
|
||||
|
||||
if currHeader.parentHash == Hash256():
|
||||
break
|
||||
|
||||
currHash = currHeader.parentHash
|
||||
if not db.getBlockHeader(currHeader.parentHash, currHeader):
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc exists*(db: CoreDbRef, hash: Hash256): bool =
|
||||
db.kvt.contains(hash.data)
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef;
|
||||
blockHash: Hash256;
|
||||
output: var BlockHeader;
|
||||
): bool =
|
||||
let data = db.kvt.get(genericHashKey(blockHash).toOpenArray)
|
||||
if data.len != 0:
|
||||
try:
|
||||
output = rlp.decode(data, BlockHeader)
|
||||
true
|
||||
except RlpError:
|
||||
false
|
||||
else:
|
||||
false
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef,
|
||||
blockHash: Hash256;
|
||||
): BlockHeader =
|
||||
## Returns the requested block header as specified by block hash.
|
||||
##
|
||||
## Raises BlockNotFound if it is not present in the db.
|
||||
if not db.getBlockHeader(blockHash, result):
|
||||
raise newException(
|
||||
BlockNotFound, "No block with hash " & blockHash.data.toHex)
|
||||
|
||||
proc getHash(
|
||||
db: CoreDbRef;
|
||||
key: DbKey;
|
||||
output: var Hash256;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
let data = db.kvt.get(key.toOpenArray)
|
||||
if data.len != 0:
|
||||
output = rlp.decode(data, Hash256)
|
||||
result = true
|
||||
|
||||
proc getCanonicalHead*(
|
||||
db: CoreDbRef;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [RlpError,EVMError].} =
|
||||
var headHash: Hash256
|
||||
if not db.getHash(canonicalHeadHashKey(), headHash) or
|
||||
not db.getBlockHeader(headHash, result):
|
||||
raise newException(
|
||||
CanonicalHeadNotFound, "No canonical head set for this chain")
|
||||
|
||||
proc getCanonicalHeaderHash*(
|
||||
db: CoreDbRef;
|
||||
): Hash256
|
||||
{.gcsafe, raises: [RlpError].}=
|
||||
discard db.getHash(canonicalHeadHashKey(), result)
|
||||
|
||||
proc getBlockHash*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
output: var Hash256;
|
||||
): bool =
|
||||
## Return the block hash for the given block number.
|
||||
db.getHash(blockNumberToHashKey(n), output)
|
||||
|
||||
proc getBlockHash*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
): Hash256
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
## Return the block hash for the given block number.
|
||||
if not db.getHash(blockNumberToHashKey(n), result):
|
||||
raise newException(BlockNotFound, "No block hash for number " & $n)
|
||||
|
||||
proc getHeadBlockHash*(
|
||||
db: CoreDbRef;
|
||||
): Hash256
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
if not db.getHash(canonicalHeadHashKey(), result):
|
||||
result = Hash256()
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
output: var BlockHeader;
|
||||
): bool =
|
||||
## Returns the block header with the given number in the canonical chain.
|
||||
var blockHash: Hash256
|
||||
if db.getBlockHash(n, blockHash):
|
||||
result = db.getBlockHeader(blockHash, output)
|
||||
|
||||
proc getBlockHeaderWithHash*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
): Option[(BlockHeader, Hash256)]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
## Returns the block header and its hash, with the given number in the canonical chain.
|
||||
## Hash is returned to avoid recomputing it
|
||||
var hash: Hash256
|
||||
if db.getBlockHash(n, hash):
|
||||
# Note: this will throw if header is not present.
|
||||
var header: BlockHeader
|
||||
if db.getBlockHeader(hash, header):
|
||||
return some((header, hash))
|
||||
else:
|
||||
# this should not happen, but if it happen lets fail laudly as this means
|
||||
# something is super wrong
|
||||
raiseAssert("Corrupted database. Mapping number->hash present, without header in database")
|
||||
else:
|
||||
return none[(BlockHeader, Hash256)]()
|
||||
|
||||
proc getBlockHeader*(
|
||||
db: CoreDbRef;
|
||||
n: BlockNumber;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
## Returns the block header with the given number in the canonical chain.
|
||||
## Raises BlockNotFound error if the block is not in the DB.
|
||||
db.getBlockHeader(db.getBlockHash(n))
|
||||
|
||||
proc getScore*(
|
||||
db: CoreDbRef;
|
||||
blockHash: Hash256;
|
||||
): UInt256
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
rlp.decode(db.kvt.get(blockHashToScoreKey(blockHash).toOpenArray), UInt256)
|
||||
|
||||
proc setScore*(db: CoreDbRef; blockHash: Hash256, score: UInt256) =
|
||||
## for testing purpose
|
||||
db.kvt.put(blockHashToScoreKey(blockHash).toOpenArray, rlp.encode(score))
|
||||
|
||||
proc getTd*(db: CoreDbRef; blockHash: Hash256, td: var UInt256): bool =
|
||||
let bytes = db.kvt.get(blockHashToScoreKey(blockHash).toOpenArray)
|
||||
if bytes.len == 0: return false
|
||||
try:
|
||||
td = rlp.decode(bytes, UInt256)
|
||||
except RlpError:
|
||||
return false
|
||||
return true
|
||||
|
||||
proc headTotalDifficulty*(
|
||||
db: CoreDbRef;
|
||||
): UInt256
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
# this is actually a combination of `getHash` and `getScore`
|
||||
const key = canonicalHeadHashKey()
|
||||
let data = db.kvt.get(key.toOpenArray)
|
||||
if data.len == 0:
|
||||
return 0.u256
|
||||
|
||||
let blockHash = rlp.decode(data, Hash256)
|
||||
rlp.decode(db.kvt.get(blockHashToScoreKey(blockHash).toOpenArray), UInt256)
|
||||
|
||||
proc getAncestorsHashes*(
|
||||
db: CoreDbRef;
|
||||
limit: UInt256;
|
||||
header: BlockHeader;
|
||||
): seq[Hash256]
|
||||
{.gcsafe, raises: [BlockNotFound].} =
|
||||
var ancestorCount = min(header.blockNumber, limit).truncate(int)
|
||||
var h = header
|
||||
|
||||
result = newSeq[Hash256](ancestorCount)
|
||||
while ancestorCount > 0:
|
||||
h = db.getBlockHeader(h.parentHash)
|
||||
result[ancestorCount - 1] = h.hash
|
||||
dec ancestorCount
|
||||
|
||||
proc addBlockNumberToHashLookup*(db: CoreDbRef; header: BlockHeader) =
|
||||
db.kvt.put(
|
||||
blockNumberToHashKey(header.blockNumber).toOpenArray,
|
||||
rlp.encode(header.hash))
|
||||
|
||||
proc persistTransactions*(
|
||||
db: CoreDbRef;
|
||||
blockNumber: BlockNumber;
|
||||
transactions: openArray[Transaction];
|
||||
): Hash256
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
var trie = db.mptPrune()
|
||||
for idx, tx in transactions:
|
||||
let
|
||||
encodedTx = rlp.encode(tx.removeNetworkPayload)
|
||||
txHash = rlpHash(tx) # beware EIP-4844
|
||||
txKey: TransactionKey = (blockNumber, idx)
|
||||
trie.put(rlp.encode(idx), encodedTx)
|
||||
db.kvt.put(transactionHashToBlockKey(txHash).toOpenArray, rlp.encode(txKey))
|
||||
trie.rootHash
|
||||
|
||||
proc getTransaction*(
|
||||
db: CoreDbRef;
|
||||
txRoot: Hash256;
|
||||
txIndex: int;
|
||||
res: var Transaction;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var db = db.mptPrune txRoot
|
||||
let txData = db.get(rlp.encode(txIndex))
|
||||
if txData.len > 0:
|
||||
res = rlp.decode(txData, Transaction)
|
||||
result = true
|
||||
|
||||
proc getTransactionCount*(
|
||||
db: CoreDbRef;
|
||||
txRoot: Hash256;
|
||||
): int
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var trie = db.mptPrune txRoot
|
||||
var txCount = 0
|
||||
while true:
|
||||
let txKey = rlp.encode(txCount)
|
||||
if txKey in trie:
|
||||
inc txCount
|
||||
else:
|
||||
return txCount
|
||||
|
||||
doAssert(false, "unreachable")
|
||||
|
||||
proc getUnclesCount*(
|
||||
db: CoreDbRef;
|
||||
ommersHash: Hash256;
|
||||
): int
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
if ommersHash != EMPTY_UNCLE_HASH:
|
||||
let encodedUncles = db.kvt.get(genericHashKey(ommersHash).toOpenArray)
|
||||
if encodedUncles.len != 0:
|
||||
let r = rlpFromBytes(encodedUncles)
|
||||
result = r.listLen
|
||||
|
||||
proc getUncles*(
|
||||
db: CoreDbRef;
|
||||
ommersHash: Hash256;
|
||||
): seq[BlockHeader]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
if ommersHash != EMPTY_UNCLE_HASH:
|
||||
let encodedUncles = db.kvt.get(genericHashKey(ommersHash).toOpenArray)
|
||||
if encodedUncles.len != 0:
|
||||
result = rlp.decode(encodedUncles, seq[BlockHeader])
|
||||
|
||||
proc persistWithdrawals*(
|
||||
db: CoreDbRef;
|
||||
withdrawals: openArray[Withdrawal];
|
||||
): Hash256
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
var trie = db.mptPrune()
|
||||
for idx, wd in withdrawals:
|
||||
let encodedWd = rlp.encode(wd)
|
||||
trie.put(rlp.encode(idx), encodedWd)
|
||||
trie.rootHash
|
||||
|
||||
proc getWithdrawals*(
|
||||
db: CoreDbRef;
|
||||
withdrawalsRoot: Hash256;
|
||||
): seq[Withdrawal]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
for encodedWd in db.getWithdrawalsData(withdrawalsRoot):
|
||||
result.add(rlp.decode(encodedWd, Withdrawal))
|
||||
|
||||
proc getBlockBody*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
output: var BlockBody;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
result = true
|
||||
output.transactions = @[]
|
||||
output.uncles = @[]
|
||||
for encodedTx in db.getBlockTransactionData(header.txRoot):
|
||||
output.transactions.add(rlp.decode(encodedTx, Transaction))
|
||||
|
||||
if header.ommersHash != EMPTY_UNCLE_HASH:
|
||||
let encodedUncles = db.kvt.get(genericHashKey(header.ommersHash).toOpenArray)
|
||||
if encodedUncles.len != 0:
|
||||
output.uncles = rlp.decode(encodedUncles, seq[BlockHeader])
|
||||
else:
|
||||
result = false
|
||||
|
||||
if header.withdrawalsRoot.isSome:
|
||||
output.withdrawals = some(db.getWithdrawals(header.withdrawalsRoot.get))
|
||||
|
||||
proc getBlockBody*(
|
||||
db: CoreDbRef;
|
||||
blockHash: Hash256;
|
||||
output: var BlockBody;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var header: BlockHeader
|
||||
if db.getBlockHeader(blockHash, header):
|
||||
return db.getBlockBody(header, output)
|
||||
|
||||
proc getBlockBody*(
|
||||
db: CoreDbRef;
|
||||
hash: Hash256;
|
||||
): BlockBody
|
||||
{.gcsafe, raises: [RlpError,ValueError].} =
|
||||
if not db.getBlockBody(hash, result):
|
||||
raise newException(ValueError, "Error when retrieving block body")
|
||||
|
||||
proc getUncleHashes*(
|
||||
db: CoreDbRef;
|
||||
blockHashes: openArray[Hash256];
|
||||
): seq[Hash256]
|
||||
{.gcsafe, raises: [RlpError,ValueError].} =
|
||||
for blockHash in blockHashes:
|
||||
var blockBody = db.getBlockBody(blockHash)
|
||||
for uncle in blockBody.uncles:
|
||||
result.add uncle.hash
|
||||
|
||||
proc getUncleHashes*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
): seq[Hash256]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
if header.ommersHash != EMPTY_UNCLE_HASH:
|
||||
let encodedUncles = db.kvt.get(genericHashKey(header.ommersHash).toOpenArray)
|
||||
if encodedUncles.len != 0:
|
||||
let uncles = rlp.decode(encodedUncles, seq[BlockHeader])
|
||||
for x in uncles:
|
||||
result.add x.hash
|
||||
|
||||
proc getTransactionKey*(
|
||||
db: CoreDbRef;
|
||||
transactionHash: Hash256;
|
||||
): tuple[blockNumber: BlockNumber, index: int]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
let tx = db.kvt.get(transactionHashToBlockKey(transactionHash).toOpenArray)
|
||||
|
||||
if tx.len > 0:
|
||||
let key = rlp.decode(tx, TransactionKey)
|
||||
result = (key.blockNumber, key.index)
|
||||
else:
|
||||
result = (0.toBlockNumber, -1)
|
||||
|
||||
proc headerExists*(db: CoreDbRef; blockHash: Hash256): bool =
|
||||
## Returns True if the header with the given block hash is in our DB.
|
||||
db.kvt.contains(genericHashKey(blockHash).toOpenArray)
|
||||
|
||||
proc setHead*(
|
||||
db: CoreDbRef;
|
||||
blockHash: Hash256;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var header: BlockHeader
|
||||
if not db.getBlockHeader(blockHash, header):
|
||||
return false
|
||||
|
||||
if not db.markCanonicalChain(header, blockHash):
|
||||
return false
|
||||
|
||||
db.kvt.put(canonicalHeadHashKey().toOpenArray, rlp.encode(blockHash))
|
||||
return true
|
||||
|
||||
proc setHead*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
writeHeader = false;
|
||||
): bool
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var headerHash = rlpHash(header)
|
||||
if writeHeader:
|
||||
db.kvt.put(genericHashKey(headerHash).toOpenArray, rlp.encode(header))
|
||||
if not db.markCanonicalChain(header, headerHash):
|
||||
return false
|
||||
db.kvt.put(canonicalHeadHashKey().toOpenArray, rlp.encode(headerHash))
|
||||
return true
|
||||
|
||||
proc persistReceipts*(
|
||||
db: CoreDbRef;
|
||||
receipts: openArray[Receipt];
|
||||
): Hash256
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
var trie = db.mptPrune()
|
||||
for idx, rec in receipts:
|
||||
trie.put(rlp.encode(idx), rlp.encode(rec))
|
||||
trie.rootHash
|
||||
|
||||
proc getReceipts*(
|
||||
db: CoreDbRef;
|
||||
receiptRoot: Hash256;
|
||||
): seq[Receipt]
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
var receipts = newSeq[Receipt]()
|
||||
for r in db.getReceipts(receiptRoot):
|
||||
receipts.add(r)
|
||||
return receipts
|
||||
|
||||
proc persistHeaderToDb*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
forceCanonical: bool;
|
||||
startOfHistory = GENESIS_PARENT_HASH;
|
||||
): seq[BlockHeader]
|
||||
{.gcsafe, raises: [RlpError,EVMError].} =
|
||||
let isStartOfHistory = header.parentHash == startOfHistory
|
||||
let headerHash = header.blockHash
|
||||
if not isStartOfHistory and not db.headerExists(header.parentHash):
|
||||
raise newException(ParentNotFound, "Cannot persist block header " &
|
||||
$headerHash & " with unknown parent " & $header.parentHash)
|
||||
db.kvt.put(genericHashKey(headerHash).toOpenArray, rlp.encode(header))
|
||||
|
||||
let score = if isStartOfHistory: header.difficulty
|
||||
else: db.getScore(header.parentHash) + header.difficulty
|
||||
db.kvt.put(blockHashToScoreKey(headerHash).toOpenArray, rlp.encode(score))
|
||||
|
||||
db.addBlockNumberToHashLookup(header)
|
||||
|
||||
var headScore: UInt256
|
||||
try:
|
||||
headScore = db.getScore(db.getCanonicalHead().hash)
|
||||
except CanonicalHeadNotFound:
|
||||
return db.setAsCanonicalChainHead(headerHash)
|
||||
|
||||
if score > headScore or forceCanonical:
|
||||
return db.setAsCanonicalChainHead(headerHash)
|
||||
|
||||
proc persistHeaderToDbWithoutSetHead*(
|
||||
db: CoreDbRef;
|
||||
header: BlockHeader;
|
||||
startOfHistory = GENESIS_PARENT_HASH;
|
||||
) {.gcsafe, raises: [RlpError].} =
|
||||
let isStartOfHistory = header.parentHash == startOfHistory
|
||||
let headerHash = header.blockHash
|
||||
let score = if isStartOfHistory: header.difficulty
|
||||
else: db.getScore(header.parentHash) + header.difficulty
|
||||
|
||||
db.kvt.put(blockHashToScoreKey(headerHash).toOpenArray, rlp.encode(score))
|
||||
db.kvt.put(genericHashKey(headerHash).toOpenArray, rlp.encode(header))
|
||||
|
||||
# FIXME-Adam: This seems like a bad idea. I don't see a way to get the score
|
||||
# in stateless mode, but it seems dangerous to just shove the header into
|
||||
# the DB *without* also storing the score.
|
||||
proc persistHeaderToDbWithoutSetHeadOrScore*(db: CoreDbRef; header: BlockHeader) =
|
||||
db.addBlockNumberToHashLookup(header)
|
||||
db.kvt.put(genericHashKey(header.blockHash).toOpenArray, rlp.encode(header))
|
||||
|
||||
proc persistUncles*(db: CoreDbRef, uncles: openArray[BlockHeader]): Hash256 =
|
||||
## Persists the list of uncles to the database.
|
||||
## Returns the uncles hash.
|
||||
let enc = rlp.encode(uncles)
|
||||
result = keccakHash(enc)
|
||||
db.kvt.put(genericHashKey(result).toOpenArray, enc)
|
||||
|
||||
proc safeHeaderHash*(
|
||||
db: CoreDbRef;
|
||||
): Hash256
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
discard db.getHash(safeHashKey(), result)
|
||||
|
||||
proc safeHeaderHash*(db: CoreDbRef, headerHash: Hash256) =
|
||||
db.kvt.put(safeHashKey().toOpenArray, rlp.encode(headerHash))
|
||||
|
||||
proc finalizedHeaderHash*(
|
||||
db: CoreDbRef;
|
||||
): Hash256
|
||||
{.gcsafe, raises: [RlpError].} =
|
||||
discard db.getHash(finalizedHashKey(), result)
|
||||
|
||||
proc finalizedHeaderHash*(db: CoreDbRef, headerHash: Hash256) =
|
||||
db.kvt.put(finalizedHashKey().toOpenArray, rlp.encode(headerHash))
|
||||
|
||||
proc safeHeader*(
|
||||
db: CoreDbRef;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
db.getBlockHeader(db.safeHeaderHash)
|
||||
|
||||
proc finalizedHeader*(
|
||||
db: CoreDbRef;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
db.getBlockHeader(db.finalizedHeaderHash)
|
||||
|
||||
proc haveBlockAndState*(db: CoreDbRef, headerHash: Hash256): bool =
|
||||
var header: BlockHeader
|
||||
if not db.getBlockHeader(headerHash, header):
|
||||
return false
|
||||
# see if stateRoot exists
|
||||
db.exists(header.stateRoot)
|
||||
|
||||
proc getBlockWitness*(db: CoreDbRef, blockHash: Hash256): seq[byte] {.gcsafe.} =
|
||||
db.kvt.get(blockHashToBlockWitnessKey(blockHash).toOpenArray)
|
||||
|
||||
proc setBlockWitness*(db: CoreDbRef, blockHash: Hash256, witness: seq[byte]) =
|
||||
db.kvt.put(blockHashToBlockWitnessKey(blockHash).toOpenArray, witness)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
|
@ -12,12 +12,11 @@
|
|||
|
||||
import
|
||||
std/options,
|
||||
eth/[common, trie/db],
|
||||
eth/common,
|
||||
../aristo,
|
||||
./backend/[aristo_db, legacy_db]
|
||||
./backend/aristo_db
|
||||
|
||||
import
|
||||
#./core_apps_legacy as core_apps -- avoid
|
||||
./core_apps_newapi as core_apps
|
||||
import
|
||||
./base except bless
|
||||
|
@ -36,10 +35,6 @@ export
|
|||
toAristoProfData,
|
||||
toAristoOldestState,
|
||||
|
||||
# see `legacy_db`
|
||||
isLegacy,
|
||||
toLegacy,
|
||||
|
||||
# Standard interface for calculating merkle hash signatures (see `aristo`)
|
||||
MerkleSignRef,
|
||||
merkleSignBegin,
|
||||
|
@ -51,17 +46,6 @@ export
|
|||
# Public constructors
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc newCoreDbRef*(
|
||||
db: TrieDatabaseRef;
|
||||
): CoreDbRef
|
||||
{.gcsafe, deprecated: "use newCoreDbRef(LegacyDbPersistent,<path>)".} =
|
||||
## Legacy constructor.
|
||||
##
|
||||
## Note: Using legacy notation `newCoreDbRef()` rather than
|
||||
## `CoreDbRef.init()` because of compiler coughing.
|
||||
##
|
||||
db.newLegacyPersistentCoreDbRef()
|
||||
|
||||
proc newCoreDbRef*(
|
||||
dbType: static[CoreDbType]; # Database type symbol
|
||||
): CoreDbRef =
|
||||
|
@ -70,10 +54,7 @@ proc newCoreDbRef*(
|
|||
## Note: Using legacy notation `newCoreDbRef()` rather than
|
||||
## `CoreDbRef.init()` because of compiler coughing.
|
||||
##
|
||||
when dbType == LegacyDbMemory:
|
||||
newLegacyMemoryCoreDbRef()
|
||||
|
||||
elif dbType == AristoDbMemory:
|
||||
when dbType == AristoDbMemory:
|
||||
newAristoMemoryCoreDbRef()
|
||||
|
||||
elif dbType == AristoDbVoid:
|
||||
|
|
|
@ -25,12 +25,11 @@ import
|
|||
../aristo,
|
||||
./memory_only,
|
||||
base_iterators_persistent,
|
||||
./backend/[aristo_rocksdb, legacy_rocksdb]
|
||||
./backend/aristo_rocksdb
|
||||
|
||||
export
|
||||
memory_only,
|
||||
base_iterators_persistent,
|
||||
toRocksStoreRef
|
||||
base_iterators_persistent
|
||||
|
||||
proc newCoreDbRef*(
|
||||
dbType: static[CoreDbType]; # Database type symbol
|
||||
|
@ -40,10 +39,7 @@ proc newCoreDbRef*(
|
|||
##
|
||||
## Note: Using legacy notation `newCoreDbRef()` rather than
|
||||
## `CoreDbRef.init()` because of compiler coughing.
|
||||
when dbType == LegacyDbPersistent:
|
||||
newLegacyPersistentCoreDbRef path
|
||||
|
||||
elif dbType == AristoDbRocks:
|
||||
when dbType == AristoDbRocks:
|
||||
newAristoRocksDbCoreDbRef path
|
||||
|
||||
else:
|
||||
|
|
|
@ -96,12 +96,8 @@ template initAccountsTrie*(db: DB, isPruning = true): AccountsTrie =
|
|||
proc getAccountBytes*(trie: AccountsTrie, address: EthAddress): seq[byte] =
|
||||
CoreDbPhkRef(trie).get(address)
|
||||
|
||||
proc maybeGetAccountBytes*(trie: AccountsTrie, address: EthAddress): Option[Blob] {.gcsafe, raises: [RlpError].} =
|
||||
let phk = CoreDbPhkRef(trie)
|
||||
if phk.parent.isLegacy:
|
||||
phk.toMpt.distinctBase.backend.toLegacy.SecureHexaryTrie.maybeGet(address)
|
||||
else:
|
||||
some(phk.get(address))
|
||||
proc maybeGetAccountBytes*(trie: AccountsTrie, address: EthAddress): Option[Blob] =
|
||||
some(CoreDbPhkRef(trie).get(address))
|
||||
|
||||
proc putAccountBytes*(trie: var AccountsTrie, address: EthAddress, value: openArray[byte]) =
|
||||
CoreDbPhkRef(trie).put(address, value)
|
||||
|
@ -131,12 +127,8 @@ template createTrieKeyFromSlot*(slot: UInt256): auto =
|
|||
proc getSlotBytes*(trie: StorageTrie, slotAsKey: openArray[byte]): seq[byte] =
|
||||
CoreDbPhkRef(trie).get(slotAsKey)
|
||||
|
||||
proc maybeGetSlotBytes*(trie: StorageTrie, slotAsKey: openArray[byte]): Option[Blob] {.gcsafe, raises: [RlpError].} =
|
||||
let phk = CoreDbPhkRef(trie)
|
||||
if phk.parent.isLegacy:
|
||||
phk.toMpt.distinctBase.backend.toLegacy.SecureHexaryTrie.maybeGet(slotAsKey)
|
||||
else:
|
||||
some(phk.get(slotAsKey))
|
||||
proc maybeGetSlotBytes*(trie: StorageTrie, slotAsKey: openArray[byte]): Option[Blob] =
|
||||
some(CoreDbPhkRef(trie).get(slotAsKey))
|
||||
|
||||
proc putSlotBytes*(trie: var StorageTrie, slotAsKey: openArray[byte], value: openArray[byte]) =
|
||||
CoreDbPhkRef(trie).put(slotAsKey, value)
|
||||
|
|
|
@ -21,7 +21,7 @@ The points of these two files are:
|
|||
|
||||
import
|
||||
chronicles,
|
||||
eth/[common, trie/db],
|
||||
eth/common,
|
||||
"."/[core_db, distinct_tries, storage_types, values_from_bytes]
|
||||
|
||||
|
||||
|
@ -55,10 +55,7 @@ proc ifNodesExistGetAccount*(trie: AccountsTrie, address: EthAddress): Option[Ac
|
|||
ifNodesExistGetAccountBytes(trie, address).map(accountFromBytes)
|
||||
|
||||
proc maybeGetCode*(db: CoreDbRef, codeHash: Hash256): Option[seq[byte]] =
|
||||
if db.isLegacy:
|
||||
db.newKvt.backend.toLegacy.maybeGet(contractHashKey(codeHash).toOpenArray)
|
||||
else:
|
||||
some(db.kvt.get(contractHashKey(codeHash).toOpenArray))
|
||||
some(db.kvt.get(contractHashKey(codeHash).toOpenArray))
|
||||
|
||||
proc maybeGetCode*(trie: AccountsTrie, address: EthAddress): Option[seq[byte]] =
|
||||
let maybeAcc = trie.ifNodesExistGetAccount(address)
|
||||
|
|
|
@ -22,20 +22,18 @@
|
|||
import
|
||||
eth/common,
|
||||
./core_db,
|
||||
./ledger/backend/[
|
||||
accounts_cache, accounts_cache_desc,
|
||||
accounts_ledger, accounts_ledger_desc],
|
||||
./ledger/base_iterators
|
||||
./ledger/backend/[accounts_ledger, accounts_ledger_desc],
|
||||
./ledger/[base_iterators, distinct_ledgers]
|
||||
|
||||
import
|
||||
./ledger/base except LedgerApiTxt, beginTrackApi, bless, ifTrackApi
|
||||
|
||||
export
|
||||
AccountsCache,
|
||||
AccountsLedgerRef,
|
||||
LedgerType,
|
||||
base,
|
||||
base_iterators,
|
||||
distinct_ledgers,
|
||||
init
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -46,14 +44,10 @@ proc init*(
|
|||
ldgType: LedgerType;
|
||||
db: CoreDbRef;
|
||||
root: Hash256;
|
||||
pruneTrie: bool;
|
||||
): LedgerRef =
|
||||
case ldgType:
|
||||
of LegacyAccountsCache:
|
||||
result = AccountsCache.init(db, root, pruneTrie)
|
||||
|
||||
of LedgerCache:
|
||||
result = AccountsLedgerRef.init(db, root, pruneTrie)
|
||||
AccountsLedgerRef.init(db, root)
|
||||
|
||||
else:
|
||||
raiseAssert: "Missing ledger type label"
|
||||
|
|
|
@ -34,7 +34,7 @@ import
|
|||
eth/[common, rlp],
|
||||
results,
|
||||
../../../stateless/multi_keys,
|
||||
"../.."/[constants, errors, utils/utils],
|
||||
"../.."/[constants, utils/utils],
|
||||
../access_list as ac_access_list,
|
||||
".."/[core_db, storage_types, transient_storage],
|
||||
./distinct_ledgers
|
||||
|
@ -650,7 +650,7 @@ iterator pairs*(ac: AccountsLedgerRef): (EthAddress, Account) =
|
|||
for address, account in ac.savePoint.cache:
|
||||
yield (address, account.statement.recast().value)
|
||||
|
||||
iterator storage*(ac: AccountsLedgerRef, address: EthAddress): (UInt256, UInt256) {.gcsafe, raises: [CoreDbApiError].} =
|
||||
iterator storage*(ac: AccountsLedgerRef, address: EthAddress): (UInt256, UInt256) =
|
||||
# beware that if the account not persisted,
|
||||
# the storage root will not be updated
|
||||
let acc = ac.getAccount(address, false)
|
||||
|
|
|
@ -1,251 +0,0 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or distributed except
|
||||
# according to those terms.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
eth/common,
|
||||
../../../../stateless/multi_keys,
|
||||
"../.."/[core_db, distinct_tries],
|
||||
../accounts_cache as impl,
|
||||
".."/[base, base/base_desc],
|
||||
./accounts_cache_desc as wrp
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
template noRlpException(info: static[string]; code: untyped) =
|
||||
try:
|
||||
code
|
||||
except RlpError as e:
|
||||
raiseAssert info & ", name=\"" & $e.name & "\", msg=\"" & e.msg & "\""
|
||||
|
||||
func savePoint(sp: LedgerSpRef): impl.SavePoint =
|
||||
wrp.SavePoint(sp).sp
|
||||
|
||||
# ----------------
|
||||
|
||||
proc ledgerMethods(lc: impl.AccountsCache): LedgerFns =
|
||||
LedgerFns(
|
||||
accessListFn: proc(eAddr: EthAddress) =
|
||||
lc.accessList(eAddr),
|
||||
|
||||
accessList2Fn: proc(eAddr: EthAddress, slot: UInt256) =
|
||||
lc.accessList(eAddr, slot),
|
||||
|
||||
accountExistsFn: proc(eAddr: EthAddress): bool =
|
||||
lc.accountExists(eAddr),
|
||||
|
||||
addBalanceFn: proc(eAddr: EthAddress, delta: UInt256) =
|
||||
lc.addBalance(eAddr, delta),
|
||||
|
||||
addLogEntryFn: proc(log: Log) =
|
||||
lc.addLogEntry(log),
|
||||
|
||||
beginSavepointFn: proc(): LedgerSpRef =
|
||||
wrp.SavePoint(sp: lc.beginSavepoint()),
|
||||
|
||||
clearStorageFn: proc(eAddr: EthAddress) =
|
||||
lc.clearStorage(eAddr),
|
||||
|
||||
clearTransientStorageFn: proc() =
|
||||
lc.clearTransientStorage(),
|
||||
|
||||
collectWitnessDataFn: proc() =
|
||||
lc.collectWitnessData(),
|
||||
|
||||
commitFn: proc(sp: LedgerSpRef) =
|
||||
lc.commit(sp.savePoint),
|
||||
|
||||
deleteAccountFn: proc(eAddr: EthAddress) =
|
||||
lc.deleteAccount(eAddr),
|
||||
|
||||
disposeFn: proc(sp: LedgerSpRef) =
|
||||
lc.dispose(sp.savePoint),
|
||||
|
||||
getAndClearLogEntriesFn: proc(): seq[Log] =
|
||||
lc.getAndClearLogEntries(),
|
||||
|
||||
getBalanceFn: proc(eAddr: EthAddress): UInt256 =
|
||||
lc.getBalance(eAddr),
|
||||
|
||||
getCodeFn: proc(eAddr: EthAddress): Blob =
|
||||
lc.getCode(eAddr),
|
||||
|
||||
getCodeHashFn: proc(eAddr: EthAddress): Hash256 =
|
||||
lc.getCodeHash(eAddr),
|
||||
|
||||
getCodeSizeFn: proc(eAddr: EthAddress): int =
|
||||
lc.getCodeSize(eAddr),
|
||||
|
||||
getCommittedStorageFn: proc(eAddr: EthAddress, slot: UInt256): UInt256 =
|
||||
noRlpException "getCommittedStorage()":
|
||||
result = lc.getCommittedStorage(eAddr, slot)
|
||||
discard,
|
||||
|
||||
getNonceFn: proc(eAddr: EthAddress): AccountNonce =
|
||||
lc.getNonce(eAddr),
|
||||
|
||||
getStorageFn: proc(eAddr: EthAddress, slot: UInt256): UInt256 =
|
||||
noRlpException "getStorageFn()":
|
||||
result = lc.getStorage(eAddr, slot)
|
||||
discard,
|
||||
|
||||
getStorageRootFn: proc(eAddr: EthAddress): Hash256 =
|
||||
lc.getStorageRoot(eAddr),
|
||||
|
||||
getTransientStorageFn: proc(eAddr: EthAddress, slot: UInt256): UInt256 =
|
||||
lc.getTransientStorage(eAddr, slot),
|
||||
|
||||
contractCollisionFn: proc(eAddr: EthAddress): bool =
|
||||
lc.contractCollision(eAddr),
|
||||
|
||||
inAccessListFn: proc(eAddr: EthAddress): bool =
|
||||
lc.inAccessList(eAddr),
|
||||
|
||||
inAccessList2Fn: proc(eAddr: EthAddress, slot: UInt256): bool =
|
||||
lc.inAccessList(eAddr, slot),
|
||||
|
||||
incNonceFn: proc(eAddr: EthAddress) =
|
||||
lc.incNonce(eAddr),
|
||||
|
||||
isDeadAccountFn: proc(eAddr: EthAddress): bool =
|
||||
lc.isDeadAccount(eAddr),
|
||||
|
||||
isEmptyAccountFn: proc(eAddr: EthAddress): bool =
|
||||
lc.isEmptyAccount(eAddr),
|
||||
|
||||
isTopLevelCleanFn: proc(): bool =
|
||||
lc.isTopLevelClean(),
|
||||
|
||||
logEntriesFn: proc(): seq[Log] =
|
||||
lc.logEntries(),
|
||||
|
||||
makeMultiKeysFn: proc(): MultiKeysRef =
|
||||
lc.makeMultiKeys(),
|
||||
|
||||
persistFn: proc(clearEmptyAccount: bool, clearCache: bool) =
|
||||
lc.persist(clearEmptyAccount, clearCache),
|
||||
|
||||
ripemdSpecialFn: proc() =
|
||||
lc.ripemdSpecial(),
|
||||
|
||||
rollbackFn: proc(sp: LedgerSpRef) =
|
||||
lc.rollback(sp.savePoint),
|
||||
|
||||
safeDisposeFn: proc(sp: LedgerSpRef) =
|
||||
if not sp.isNil:
|
||||
lc.safeDispose(sp.savePoint)
|
||||
discard,
|
||||
|
||||
selfDestructFn: proc(eAddr: EthAddress) =
|
||||
lc.selfDestruct(eAddr),
|
||||
|
||||
selfDestruct6780Fn: proc(eAddr: EthAddress) =
|
||||
lc.selfDestruct6780(eAddr),
|
||||
|
||||
selfDestructLenFn: proc(): int =
|
||||
lc.selfDestructLen(),
|
||||
|
||||
setBalanceFn: proc(eAddr: EthAddress, balance: UInt256) =
|
||||
lc.setBalance(eAddr, balance),
|
||||
|
||||
setCodeFn: proc(eAddr: EthAddress, code: Blob) =
|
||||
lc.setCode(eAddr, code),
|
||||
|
||||
setNonceFn: proc(eAddr: EthAddress, nonce: AccountNonce) =
|
||||
lc.setNonce(eAddr, nonce),
|
||||
|
||||
setStorageFn: proc(eAddr: EthAddress, slot, val: UInt256) =
|
||||
noRlpException "setStorage()":
|
||||
lc.setStorage(eAddr, slot, val)
|
||||
discard,
|
||||
|
||||
setTransientStorageFn: proc(eAddr: EthAddress, slot, val: UInt256) =
|
||||
lc.setTransientStorage(eAddr, slot, val),
|
||||
|
||||
# Renamed from `rootHashFn`
|
||||
stateFn: proc(): Hash256 =
|
||||
lc.rootHash(),
|
||||
|
||||
subBalanceFn: proc(eAddr: EthAddress, delta: UInt256) =
|
||||
lc.subBalance(eAddr, delta),
|
||||
|
||||
getAccessListFn: proc(): common.AccessList =
|
||||
lc.getAccessList())
|
||||
|
||||
proc ledgerExtras(lc: impl.AccountsCache): LedgerExtras =
|
||||
LedgerExtras(
|
||||
getMptFn: proc(): CoreDbMptRef =
|
||||
lc.rawTrie.mpt,
|
||||
|
||||
rawRootHashFn: proc(): Hash256 =
|
||||
lc.rawTrie.rootHash())
|
||||
|
||||
|
||||
proc newLegacyAccountsCache(
|
||||
db: CoreDbRef;
|
||||
root: Hash256;
|
||||
pruneTrie: bool): LedgerRef =
|
||||
## Constructor
|
||||
let lc = impl.AccountsCache.init(db, root, pruneTrie)
|
||||
wrp.AccountsCache(
|
||||
ldgType: LegacyAccountsCache,
|
||||
ac: lc,
|
||||
extras: lc.ledgerExtras(),
|
||||
methods: lc.ledgerMethods()).bless db
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public iterators
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
iterator accountsIt*(lc: wrp.AccountsCache): Account =
|
||||
for w in lc.ac.accounts():
|
||||
yield w
|
||||
|
||||
iterator addressesIt*(lc: wrp.AccountsCache): EthAddress =
|
||||
for w in lc.ac.addresses():
|
||||
yield w
|
||||
|
||||
iterator cachedStorageIt*(
|
||||
lc: wrp.AccountsCache;
|
||||
eAddr: EthAddress;
|
||||
): (UInt256,UInt256) =
|
||||
for w in lc.ac.cachedStorage(eAddr):
|
||||
yield w
|
||||
|
||||
iterator pairsIt*(lc: wrp.AccountsCache): (EthAddress,Account) =
|
||||
for w in lc.ac.pairs():
|
||||
yield w
|
||||
|
||||
iterator storageIt*(
|
||||
lc: wrp.AccountsCache;
|
||||
eAddr: EthAddress;
|
||||
): (UInt256,UInt256)
|
||||
{.gcsafe, raises: [CoreDbApiError].} =
|
||||
noRlpException "storage()":
|
||||
for w in lc.ac.storage(eAddr):
|
||||
yield w
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public constructor
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc init*(
|
||||
T: type wrp.AccountsCache;
|
||||
db: CoreDbRef;
|
||||
root: Hash256;
|
||||
pruneTrie: bool): LedgerRef =
|
||||
db.newLegacyAccountsCache(root, pruneTrie)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
|
@ -1,22 +0,0 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2023 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or distributed except
|
||||
# according to those terms.
|
||||
|
||||
import
|
||||
../accounts_cache as impl,
|
||||
../base/base_desc
|
||||
|
||||
type
|
||||
AccountsCache* = ref object of LedgerRef
|
||||
ac*: impl.AccountsCache
|
||||
|
||||
SavePoint* = ref object of LedgerSpRef
|
||||
sp*: impl.SavePoint
|
||||
|
||||
# End
|
|
@ -180,8 +180,8 @@ proc ledgerExtras(lc: impl.AccountsLedgerRef): LedgerExtras =
|
|||
proc newAccountsLedgerRef(
|
||||
db: CoreDbRef;
|
||||
root: Hash256;
|
||||
pruneTrie: bool): LedgerRef =
|
||||
let lc = impl.AccountsLedgerRef.init(db, root, pruneTrie)
|
||||
): LedgerRef =
|
||||
let lc = impl.AccountsLedgerRef.init(db, root)
|
||||
wrp.AccountsLedgerRef(
|
||||
ldgType: LedgerCache,
|
||||
ac: lc,
|
||||
|
@ -214,8 +214,7 @@ iterator pairsIt*(lc: wrp.AccountsLedgerRef): (EthAddress,Account) =
|
|||
iterator storageIt*(
|
||||
lc: wrp.AccountsLedgerRef;
|
||||
eAddr: EthAddress;
|
||||
): (UInt256,UInt256)
|
||||
{.gcsafe, raises: [CoreDbApiError].} =
|
||||
): (UInt256,UInt256) =
|
||||
for w in lc.ac.storage(eAddr):
|
||||
yield w
|
||||
|
||||
|
@ -227,8 +226,9 @@ proc init*(
|
|||
T: type wrp.AccountsLedgerRef;
|
||||
db: CoreDbRef;
|
||||
root: Hash256;
|
||||
pruneTrie: bool): LedgerRef =
|
||||
db.newAccountsLedgerRef(root, pruneTrie)
|
||||
pruneTrie = false;
|
||||
): LedgerRef =
|
||||
db.newAccountsLedgerRef root
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
|
|
|
@ -38,6 +38,7 @@ type
|
|||
LdgDeleteAccountFn = "deleteAccount"
|
||||
LdgDisposeFn = "dispose"
|
||||
LdgGetAccessListFn = "getAcessList"
|
||||
LdgGetAccountFn = "getAccount"
|
||||
LdgGetAndClearLogEntriesFn = "getAndClearLogEntries"
|
||||
LdgGetBalanceFn = "getBalance"
|
||||
LdgGetCodeFn = "getCode"
|
||||
|
|
|
@ -28,7 +28,6 @@ type
|
|||
|
||||
LedgerType* = enum
|
||||
Ooops = 0
|
||||
LegacyAccountsCache,
|
||||
LedgerCache
|
||||
|
||||
LedgerSpRef* = ref object of RootRef
|
||||
|
|
|
@ -31,6 +31,7 @@ proc validate*(ldg: LedgerRef) =
|
|||
doAssert not ldg.methods.commitFn.isNil
|
||||
doAssert not ldg.methods.deleteAccountFn.isNil
|
||||
doAssert not ldg.methods.disposeFn.isNil
|
||||
doAssert not ldg.methods.getAccessListFn.isNil
|
||||
doAssert not ldg.methods.getAndClearLogEntriesFn.isNil
|
||||
doAssert not ldg.methods.getBalanceFn.isNil
|
||||
doAssert not ldg.methods.getCodeFn.isNil
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
import
|
||||
eth/common,
|
||||
../core_db,
|
||||
./backend/[accounts_cache, accounts_cache_desc,
|
||||
accounts_ledger, accounts_ledger_desc],
|
||||
./backend/[accounts_ledger, accounts_ledger_desc],
|
||||
./base/api_tracking,
|
||||
./base
|
||||
|
||||
|
@ -39,9 +38,6 @@ when LedgerEnableApiTracking:
|
|||
iterator accounts*(ldg: LedgerRef): Account =
|
||||
ldg.beginTrackApi LdgAccountsIt
|
||||
case ldg.ldgType:
|
||||
of LegacyAccountsCache:
|
||||
for w in ldg.AccountsCache.accountsIt():
|
||||
yield w
|
||||
of LedgerCache:
|
||||
for w in ldg.AccountsLedgerRef.accountsIt():
|
||||
yield w
|
||||
|
@ -53,9 +49,6 @@ iterator accounts*(ldg: LedgerRef): Account =
|
|||
iterator addresses*(ldg: LedgerRef): EthAddress =
|
||||
ldg.beginTrackApi LdgAdressesIt
|
||||
case ldg.ldgType:
|
||||
of LegacyAccountsCache:
|
||||
for w in ldg.AccountsCache.addressesIt():
|
||||
yield w
|
||||
of LedgerCache:
|
||||
for w in ldg.AccountsLedgerRef.addressesIt():
|
||||
yield w
|
||||
|
@ -67,9 +60,6 @@ iterator addresses*(ldg: LedgerRef): EthAddress =
|
|||
iterator cachedStorage*(ldg: LedgerRef, eAddr: EthAddress): (UInt256,UInt256) =
|
||||
ldg.beginTrackApi LdgCachedStorageIt
|
||||
case ldg.ldgType:
|
||||
of LegacyAccountsCache:
|
||||
for w in ldg.AccountsCache.cachedStorageIt(eAddr):
|
||||
yield w
|
||||
of LedgerCache:
|
||||
for w in ldg.AccountsLedgerRef.cachedStorageIt(eAddr):
|
||||
yield w
|
||||
|
@ -81,9 +71,6 @@ iterator cachedStorage*(ldg: LedgerRef, eAddr: EthAddress): (UInt256,UInt256) =
|
|||
iterator pairs*(ldg: LedgerRef): (EthAddress,Account) =
|
||||
ldg.beginTrackApi LdgPairsIt
|
||||
case ldg.ldgType:
|
||||
of LegacyAccountsCache:
|
||||
for w in ldg.AccountsCache.pairsIt():
|
||||
yield w
|
||||
of LedgerCache:
|
||||
for w in ldg.AccountsLedgerRef.pairsIt():
|
||||
yield w
|
||||
|
@ -95,13 +82,9 @@ iterator pairs*(ldg: LedgerRef): (EthAddress,Account) =
|
|||
iterator storage*(
|
||||
ldg: LedgerRef;
|
||||
eAddr: EthAddress;
|
||||
): (UInt256,UInt256)
|
||||
{.gcsafe, raises: [CoreDbApiError].} =
|
||||
): (UInt256,UInt256) =
|
||||
ldg.beginTrackApi LdgStorageIt
|
||||
case ldg.ldgType:
|
||||
of LegacyAccountsCache:
|
||||
for w in ldg.AccountsCache.storageIt(eAddr):
|
||||
yield w
|
||||
of LedgerCache:
|
||||
for w in ldg.AccountsLedgerRef.storageIt(eAddr):
|
||||
yield w
|
||||
|
|
|
@ -236,8 +236,7 @@ proc delete*(sl: StorageLedger, slot: UInt256) =
|
|||
iterator storage*(
|
||||
al: AccountLedger;
|
||||
account: CoreDbAccount;
|
||||
): (Blob,Blob)
|
||||
{.gcsafe, raises: [CoreDbApiError].} =
|
||||
): (Blob,Blob) =
|
||||
## For given account, iterate over storage slots
|
||||
const
|
||||
info = "storage(): "
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2019-2023 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
# http://opensource.org/licenses/MIT)
|
||||
# at your option. This file may not be copied, modified, or distributed except
|
||||
# according to those terms.
|
||||
|
||||
import eth/trie/db
|
||||
|
||||
type
|
||||
CaptureFlags* {.pure.} = enum
|
||||
PersistPut
|
||||
PersistDel
|
||||
|
||||
DB = TrieDatabaseRef
|
||||
|
||||
CaptureDB* = ref object of RootObj
|
||||
srcDb: DB
|
||||
dstDb: DB
|
||||
flags: set[CaptureFlags]
|
||||
|
||||
proc get*(db: CaptureDB, key: openArray[byte]): seq[byte] =
|
||||
result = db.dstDb.get(key)
|
||||
if result.len != 0: return
|
||||
result = db.srcDb.get(key)
|
||||
if result.len != 0:
|
||||
db.dstDb.put(key, result)
|
||||
|
||||
proc put*(db: CaptureDB, key, value: openArray[byte]) =
|
||||
db.dstDb.put(key, value)
|
||||
if CaptureFlags.PersistPut in db.flags:
|
||||
db.srcDb.put(key, value)
|
||||
|
||||
proc contains*(db: CaptureDB, key: openArray[byte]): bool =
|
||||
result = db.srcDb.contains(key)
|
||||
doAssert(db.dstDb.contains(key) == result)
|
||||
|
||||
proc del*(db: CaptureDB, key: openArray[byte]) =
|
||||
db.dstDb.del(key)
|
||||
if CaptureFlags.PersistDel in db.flags:
|
||||
db.srcDb.del(key)
|
||||
|
||||
proc newCaptureDB*(srcDb, dstDb: DB, flags: set[CaptureFlags] = {}): CaptureDB =
|
||||
result.new()
|
||||
result.srcDb = srcDb
|
||||
result.dstDb = dstDb
|
||||
result.flags = flags
|
|
@ -59,9 +59,6 @@ type
|
|||
AccountProof* = seq[MptNodeRlpBytes]
|
||||
SlotProof* = seq[MptNodeRlpBytes]
|
||||
|
||||
proc pruneTrie*(db: AccountStateDB): bool =
|
||||
db.trie.isPruning
|
||||
|
||||
proc db*(db: AccountStateDB): CoreDbRef =
|
||||
db.trie.db
|
||||
|
||||
|
@ -75,9 +72,9 @@ proc `rootHash=`*(db: AccountStateDB, root: KeccakHash) =
|
|||
db.trie = initAccountsTrie(db.trie.db, root, db.trie.isPruning)
|
||||
|
||||
proc newAccountStateDB*(backingStore: CoreDbRef,
|
||||
root: KeccakHash, pruneTrie: bool): AccountStateDB =
|
||||
root: KeccakHash): AccountStateDB =
|
||||
result.new()
|
||||
result.trie = initAccountsTrie(backingStore, root, pruneTrie)
|
||||
result.trie = initAccountsTrie(backingStore, root)
|
||||
result.originalRoot = root
|
||||
#result.transactionID = backingStore.getTransactionID()
|
||||
when aleth_compat:
|
||||
|
|
|
@ -78,7 +78,7 @@ proc new*(
|
|||
## with the `parent` block header.
|
||||
new result
|
||||
result.init(
|
||||
ac = com.ledgerType.init(com.db, parent.stateRoot, com.pruneTrie),
|
||||
ac = com.ledgerType.init(com.db, parent.stateRoot),
|
||||
parent = parent,
|
||||
blockCtx = blockCtx,
|
||||
com = com,
|
||||
|
@ -103,7 +103,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
|
|||
com = self.com
|
||||
db = com.db
|
||||
ac = if self.stateDB.rootHash == parent.stateRoot: self.stateDB
|
||||
else: com.ledgerType.init(db, parent.stateRoot, com.pruneTrie)
|
||||
else: com.ledgerType.init(db, parent.stateRoot)
|
||||
flags = self.flags
|
||||
self[].reset
|
||||
self.init(
|
||||
|
@ -160,7 +160,7 @@ proc init*(
|
|||
## It requires the `header` argument properly initalised so that for PoA
|
||||
## networks, the miner address is retrievable via `ecRecover()`.
|
||||
self.init(
|
||||
ac = com.ledgerType.init(com.db, parent.stateRoot, com.pruneTrie),
|
||||
ac = com.ledgerType.init(com.db, parent.stateRoot),
|
||||
parent = parent,
|
||||
blockCtx = com.blockCtx(header),
|
||||
com = com,
|
||||
|
@ -227,7 +227,7 @@ proc statelessInit*(
|
|||
tracer: TracerRef = nil): bool
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
vmState.init(
|
||||
ac = com.ledgerType.init(com.db, parent.stateRoot, com.pruneTrie),
|
||||
ac = com.ledgerType.init(com.db, parent.stateRoot),
|
||||
parent = parent,
|
||||
blockCtx = com.blockCtx(header),
|
||||
com = com,
|
||||
|
|
|
@ -148,7 +148,7 @@ proc wdNode(ctx: GraphqlContextRef, wd: Withdrawal): Node =
|
|||
proc getStateDB(com: CommonRef, header: common.BlockHeader): ReadOnlyStateDB =
|
||||
## Retrieves the account db from canonical head
|
||||
## we don't use accounst_cache here because it's read only operations
|
||||
let ac = newAccountStateDB(com.db, header.stateRoot, com.pruneTrie)
|
||||
let ac = newAccountStateDB(com.db, header.stateRoot)
|
||||
ReadOnlyStateDB(ac)
|
||||
|
||||
proc getBlockByNumber(ctx: GraphqlContextRef, number: Node): RespResult =
|
||||
|
|
|
@ -135,10 +135,10 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
|
|||
nimbus.txPool)
|
||||
of ProtocolFlag.Les:
|
||||
nimbus.ethNode.addCapability les
|
||||
of ProtocolFlag.Snap:
|
||||
nimbus.ethNode.addSnapHandlerCapability(
|
||||
nimbus.ethNode.peerPool,
|
||||
nimbus.chainRef)
|
||||
#of ProtocolFlag.Snap:
|
||||
# nimbus.ethNode.addSnapHandlerCapability(
|
||||
# nimbus.ethNode.peerPool,
|
||||
# nimbus.chainRef)
|
||||
# Cannot do without minimal `eth` capability
|
||||
if ProtocolFlag.Eth notin protocols:
|
||||
nimbus.ethNode.addEthHandlerCapability(
|
||||
|
@ -157,14 +157,14 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
|
|||
nimbus.fullSyncRef = FullSyncRef.init(
|
||||
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
||||
tickerOK, exCtrlFile)
|
||||
of SyncMode.Snap:
|
||||
# Minimal capability needed for sync only
|
||||
if ProtocolFlag.Snap notin protocols:
|
||||
nimbus.ethNode.addSnapHandlerCapability(
|
||||
nimbus.ethNode.peerPool)
|
||||
nimbus.snapSyncRef = SnapSyncRef.init(
|
||||
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
||||
tickerOK, exCtrlFile)
|
||||
#of SyncMode.Snap:
|
||||
# # Minimal capability needed for sync only
|
||||
# if ProtocolFlag.Snap notin protocols:
|
||||
# nimbus.ethNode.addSnapHandlerCapability(
|
||||
# nimbus.ethNode.peerPool)
|
||||
# nimbus.snapSyncRef = SnapSyncRef.init(
|
||||
# nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
||||
# tickerOK, exCtrlFile)
|
||||
of SyncMode.Stateless:
|
||||
# FIXME-Adam: what needs to go here?
|
||||
nimbus.statelessSyncRef = StatelessSyncRef.init()
|
||||
|
@ -192,7 +192,9 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
|
|||
if conf.maxPeers > 0:
|
||||
var waitForPeers = true
|
||||
case conf.syncMode:
|
||||
of SyncMode.Snap, SyncMode.Stateless:
|
||||
#of SyncMode.Snap:
|
||||
# waitForPeers = false
|
||||
of SyncMode.Stateless:
|
||||
waitForPeers = false
|
||||
of SyncMode.Full, SyncMode.Default:
|
||||
discard
|
||||
|
@ -283,11 +285,11 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
|
|||
let coreDB =
|
||||
# Resolve statically for database type
|
||||
case conf.chainDbMode:
|
||||
of Prune,Archive: LegacyDbPersistent.newCoreDbRef(string conf.dataDir)
|
||||
of Aristo: AristoDbRocks.newCoreDbRef(string conf.dataDir)
|
||||
of Aristo,AriPrune:
|
||||
AristoDbRocks.newCoreDbRef(string conf.dataDir)
|
||||
let com = CommonRef.new(
|
||||
db = coreDB,
|
||||
pruneTrie = (conf.chainDbMode == ChainDbMode.Prune),
|
||||
pruneHistory = (conf.chainDbMode == AriPrune),
|
||||
networkId = conf.networkId,
|
||||
params = conf.networkParams)
|
||||
|
||||
|
@ -332,8 +334,8 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
|
|||
nimbus.fullSyncRef.start
|
||||
of SyncMode.Stateless:
|
||||
nimbus.statelessSyncRef.start
|
||||
of SyncMode.Snap:
|
||||
nimbus.snapSyncRef.start
|
||||
#of SyncMode.Snap:
|
||||
# nimbus.snapSyncRef.start
|
||||
|
||||
if nimbus.state == NimbusState.Starting:
|
||||
# it might have been set to "Stopping" with Ctrl+C
|
||||
|
|
|
@ -18,7 +18,7 @@ import
|
|||
./sync/peers,
|
||||
./sync/beacon,
|
||||
./sync/legacy,
|
||||
./sync/snap,
|
||||
# ./sync/snap, # -- todo
|
||||
./sync/stateless,
|
||||
./sync/full,
|
||||
./beacon/beacon_engine,
|
||||
|
@ -36,7 +36,7 @@ export
|
|||
peers,
|
||||
beacon,
|
||||
legacy,
|
||||
snap,
|
||||
#snap,
|
||||
stateless,
|
||||
full,
|
||||
beacon_engine,
|
||||
|
@ -59,7 +59,7 @@ type
|
|||
networkLoop*: Future[void]
|
||||
peerManager*: PeerManagerRef
|
||||
legaSyncRef*: LegacySyncRef
|
||||
snapSyncRef*: SnapSyncRef
|
||||
# snapSyncRef*: SnapSyncRef # -- todo
|
||||
fullSyncRef*: FullSyncRef
|
||||
beaconSyncRef*: BeaconSyncRef
|
||||
statelessSyncRef*: StatelessSyncRef
|
||||
|
@ -82,8 +82,8 @@ proc stop*(nimbus: NimbusNode, conf: NimbusConf) {.async, gcsafe.} =
|
|||
await nimbus.peerManager.stop()
|
||||
if nimbus.statelessSyncRef.isNil.not:
|
||||
nimbus.statelessSyncRef.stop()
|
||||
if nimbus.snapSyncRef.isNil.not:
|
||||
nimbus.snapSyncRef.stop()
|
||||
#if nimbus.snapSyncRef.isNil.not:
|
||||
# nimbus.snapSyncRef.stop()
|
||||
if nimbus.fullSyncRef.isNil.not:
|
||||
nimbus.fullSyncRef.stop()
|
||||
if nimbus.beaconSyncRef.isNil.not:
|
||||
|
|
|
@ -90,7 +90,7 @@ proc setupExpRpc*(com: CommonRef, server: RpcServer) =
|
|||
proc getStateDB(header: BlockHeader): ReadOnlyStateDB =
|
||||
## Retrieves the account db from canonical head
|
||||
# we don't use accounst_cache here because it's only read operations
|
||||
let ac = newAccountStateDB(chainDB, header.stateRoot, com.pruneTrie)
|
||||
let ac = newAccountStateDB(chainDB, header.stateRoot)
|
||||
result = ReadOnlyStateDB(ac)
|
||||
|
||||
server.rpc("exp_getWitnessByBlockNumber") do(quantityTag: BlockTag, statePostExecution: bool) -> seq[byte]:
|
||||
|
|
|
@ -72,7 +72,7 @@ proc setupEthRpc*(
|
|||
proc getStateDB(header: BlockHeader): ReadOnlyStateDB =
|
||||
## Retrieves the account db from canonical head
|
||||
# we don't use accounst_cache here because it's only read operations
|
||||
let ac = newAccountStateDB(chainDB, header.stateRoot, com.pruneTrie)
|
||||
let ac = newAccountStateDB(chainDB, header.stateRoot)
|
||||
result = ReadOnlyStateDB(ac)
|
||||
|
||||
proc stateDBFromTag(quantityTag: BlockTag, readOnly = true): ReadOnlyStateDB
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
|
||||
import
|
||||
./handlers/eth as handlers_eth,
|
||||
./handlers/setup as handlers_setup,
|
||||
./handlers/snap as handlers_snap
|
||||
./handlers/setup as handlers_setup
|
||||
#./handlers/snap as handlers_snap # -- todo
|
||||
|
||||
export
|
||||
handlers_eth, handlers_setup,
|
||||
handlers_snap
|
||||
handlers_eth, handlers_setup
|
||||
#handlers_snap
|
||||
|
||||
static:
|
||||
type
|
||||
|
|
|
@ -46,20 +46,21 @@ proc addEthHandlerCapability*(
|
|||
# Public functions: convenience mappings for `snap`
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
import
|
||||
./snap as handlers_snap
|
||||
when false: # needs to be updated
|
||||
import
|
||||
./snap as handlers_snap
|
||||
|
||||
proc addSnapHandlerCapability*(
|
||||
node: EthereumNode;
|
||||
peerPool: PeerPool;
|
||||
chain = ChainRef(nil);
|
||||
) =
|
||||
## Install `snap` handlers,Passing `chein` as `nil` installs the handler
|
||||
## in minimal/outbound mode.
|
||||
if chain.isNil:
|
||||
node.addCapability protocol.snap
|
||||
else:
|
||||
node.addCapability(protocol.snap, SnapWireRef.init(chain, peerPool))
|
||||
proc addSnapHandlerCapability*(
|
||||
node: EthereumNode;
|
||||
peerPool: PeerPool;
|
||||
chain = ChainRef(nil);
|
||||
) =
|
||||
## Install `snap` handlers,Passing `chein` as `nil` installs the handler
|
||||
## in minimal/outbound mode.
|
||||
if chain.isNil:
|
||||
node.addCapability protocol.snap
|
||||
else:
|
||||
node.addCapability(protocol.snap, SnapWireRef.init(chain, peerPool))
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
|
|
|
@ -169,7 +169,7 @@ proc traceTransaction*(com: CommonRef, header: BlockHeader,
|
|||
# internal transactions:
|
||||
let
|
||||
saveCtxBefore = setCtx beforeCtx
|
||||
stateBefore = AccountsLedgerRef.init(capture.recorder, beforeRoot, com.pruneTrie)
|
||||
stateBefore = AccountsLedgerRef.init(capture.recorder, beforeRoot)
|
||||
defer:
|
||||
saveCtxBefore.setCtx().ctx.forget()
|
||||
|
||||
|
@ -208,7 +208,7 @@ proc dumpBlockState*(com: CommonRef, header: BlockHeader, body: BlockBody, dumpS
|
|||
var
|
||||
before = newJArray()
|
||||
after = newJArray()
|
||||
stateBefore = AccountsLedgerRef.init(capture.recorder, parent.stateRoot, com.pruneTrie)
|
||||
stateBefore = AccountsLedgerRef.init(capture.recorder, parent.stateRoot)
|
||||
|
||||
for idx, tx in body.transactions:
|
||||
let sender = tx.getSender
|
||||
|
|
|
@ -89,7 +89,7 @@ proc calculateTransactionData(
|
|||
## - root of transactions trie
|
||||
## - list of transactions hashes
|
||||
## - total size of transactions in block
|
||||
var tr = newCoreDbRef(LegacyDbMemory).mptPrune
|
||||
var tr = newCoreDbRef(DefaultDbMemory).mptPrune
|
||||
var txHashes: seq[TxOrHash]
|
||||
var txSize: uint64
|
||||
for i, t in items:
|
||||
|
|
|
@ -69,7 +69,7 @@ proc main() =
|
|||
|
||||
let
|
||||
blockEnv = json.parseFile(paramStr(1))
|
||||
memoryDB = newCoreDbRef(LegacyDbMemory)
|
||||
memoryDB = newCoreDbRef(DefaultDbMemory)
|
||||
blockNumber = UInt256.fromHex(blockEnv["blockNumber"].getStr())
|
||||
|
||||
prepareBlockEnv(blockEnv, memoryDB)
|
||||
|
|
|
@ -47,7 +47,7 @@ proc dumpDebug(com: CommonRef, blockNumber: UInt256) =
|
|||
|
||||
proc main() {.used.} =
|
||||
let conf = getConfiguration()
|
||||
let com = CommonRef.new(newCoreDbRef(LegacyDbPersistent, conf.dataDir), false)
|
||||
let com = CommonRef.new(newCoreDbRef(DefaultDbPersistent, conf.dataDir))
|
||||
|
||||
if conf.head != 0.u256:
|
||||
dumpDebug(com, conf.head)
|
||||
|
|
|
@ -38,8 +38,8 @@ proc parseU256(val: string): UInt256 =
|
|||
proc prepareBlockEnv(parent: BlockHeader, thisBlock: Block): CoreDbRef =
|
||||
var
|
||||
accounts = requestPostState(thisBlock)
|
||||
memoryDB = newCoreDbRef LegacyDbMemory
|
||||
accountDB = newAccountStateDB(memoryDB, parent.stateRoot, false)
|
||||
memoryDB = newCoreDbRef DefaultDbMemory
|
||||
accountDB = newAccountStateDB(memoryDB, parent.stateRoot)
|
||||
parentNumber = %(parent.blockNumber.prefixHex)
|
||||
|
||||
for address, account in accounts:
|
||||
|
@ -104,7 +104,7 @@ proc huntProblematicBlock(blockNumber: UInt256): ValidationResult =
|
|||
memoryDB = prepareBlockEnv(parentBlock.header, thisBlock)
|
||||
|
||||
# try to execute current block
|
||||
com = CommonRef.new(memoryDB, false)
|
||||
com = CommonRef.new(memoryDB)
|
||||
|
||||
discard com.db.setHead(parentBlock.header, true)
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ proc main() {.used.} =
|
|||
|
||||
let conf = configuration.getConfiguration()
|
||||
let com = CommonRef.new(
|
||||
newCoreDbRef(LegacyDbPersistent, conf.dataDir),
|
||||
false, conf.netId, networkParams(conf.netId))
|
||||
newCoreDbRef(DefaultDbPersistent, conf.dataDir),
|
||||
conf.netId, networkParams(conf.netId))
|
||||
|
||||
# move head to block number ...
|
||||
if conf.head != 0.u256:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2020-2023 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
@ -19,7 +19,7 @@ proc generatePrestate*(nimbus, geth: JsonNode, blockNumber: UInt256, parent, hea
|
|||
headerHash = rlpHash(header)
|
||||
|
||||
var
|
||||
chainDB = newCoreDbRef(LegacyDbMemory)
|
||||
chainDB = newCoreDbRef(DefaultDbMemory)
|
||||
|
||||
discard chainDB.setHead(parent, true)
|
||||
discard chainDB.persistTransactions(blockNumber, body.transactions)
|
||||
|
|
|
@ -52,7 +52,7 @@ proc validateBlock(com: CommonRef, blockNumber: BlockNumber): BlockNumber =
|
|||
proc main() {.used.} =
|
||||
let
|
||||
conf = getConfiguration()
|
||||
com = CommonRef.new(newCoreDbRef(LegacyDbPersistent, conf.dataDir), false)
|
||||
com = CommonRef.new(newCoreDbRef(DefaultDbPersistent, conf.dataDir))
|
||||
|
||||
# move head to block number ...
|
||||
if conf.head == 0.u256:
|
||||
|
|
|
@ -30,7 +30,7 @@ proc testGetBranch(tester: Tester, rootHash: KeccakHash, testStatusIMPL: var Tes
|
|||
var wb = initWitnessBuilder(tester.memDB, rootHash, flags)
|
||||
var witness = wb.buildWitness(tester.keys)
|
||||
|
||||
var db = newCoreDbRef(LegacyDbMemory)
|
||||
var db = newCoreDbRef(DefaultDbMemory)
|
||||
when defined(useInputStream):
|
||||
var input = memoryInput(witness)
|
||||
var tb = initTreeBuilder(input, db, flags)
|
||||
|
@ -87,8 +87,8 @@ proc setupStateDB(tester: var Tester, wantedState: JsonNode, stateDB: LedgerRef)
|
|||
|
||||
proc testBlockWitness(node: JsonNode, rootHash: Hash256, testStatusIMPL: var TestStatus) =
|
||||
var
|
||||
tester = Tester(memDB: newCoreDbRef(LegacyDbMemory))
|
||||
ac = AccountsCache.init(tester.memDB, emptyRlpHash, true)
|
||||
tester = Tester(memDB: newCoreDbRef(DefaultDbMemory))
|
||||
ac = LedgerCache.init(tester.memDB, emptyRlpHash)
|
||||
|
||||
let root = tester.setupStateDB(node, ac)
|
||||
if rootHash != emptyRlpHash:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue