mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-02 23:35:31 +00:00
Remove AccountStateDB (#2368)
* Remove AccountStateDB AccountStateDB should no longer be used. It's usage have been reduce to read only operations. Replace it with LedgerRef to reduce maintenance burden. * remove extra spaces Co-authored-by: tersec <tersec@users.noreply.github.com> --------- Co-authored-by: tersec <tersec@users.noreply.github.com>
This commit is contained in:
parent
a36aa95fab
commit
69044dda60
@ -988,7 +988,7 @@ proc finalizedHeaderHash*(db: CoreDbRef, headerHash: Hash256) =
|
||||
proc safeHeader*(
|
||||
db: CoreDbRef;
|
||||
): BlockHeader
|
||||
{.gcsafe, raises: [RlpError,BlockNotFound].} =
|
||||
{.gcsafe, raises: [BlockNotFound].} =
|
||||
db.getBlockHeader(db.safeHeaderHash)
|
||||
|
||||
proc finalizedHeader*(
|
||||
|
@ -152,8 +152,8 @@ proc init*(x: typedesc[AccountsLedgerRef], db: CoreDbRef,
|
||||
result.witnessCache = Table[EthAddress, WitnessData]()
|
||||
discard result.beginSavepoint
|
||||
|
||||
proc init*(x: typedesc[AccountsLedgerRef], db: CoreDbRef, pruneTrie = true): AccountsLedgerRef =
|
||||
init(x, db, EMPTY_ROOT_HASH, pruneTrie)
|
||||
proc init*(x: typedesc[AccountsLedgerRef], db: CoreDbRef): AccountsLedgerRef =
|
||||
init(x, db, EMPTY_ROOT_HASH)
|
||||
|
||||
# Renamed `rootHash()` => `state()`
|
||||
proc state*(ac: AccountsLedgerRef): KeccakHash =
|
||||
@ -784,6 +784,17 @@ func getAccessList*(ac: AccountsLedgerRef): common.AccessList =
|
||||
doAssert(ac.savePoint.parentSavepoint.isNil)
|
||||
ac.savePoint.accessList.getAccessList()
|
||||
|
||||
proc getEthAccount*(ac: AccountsLedgerRef, address: EthAddress): Account =
|
||||
let acc = ac.getAccount(address, false)
|
||||
if acc.isNil:
|
||||
return emptyEthAccount
|
||||
|
||||
## Convert to legacy object, will throw an assert if that fails
|
||||
let rc = acc.statement.recast()
|
||||
if rc.isErr:
|
||||
raiseAssert "getAccount(): cannot convert account: " & $$rc.error
|
||||
rc.value
|
||||
|
||||
proc state*(db: ReadOnlyStateDB): KeccakHash {.borrow.}
|
||||
proc getCodeHash*(db: ReadOnlyStateDB, address: EthAddress): Hash256 {.borrow.}
|
||||
proc getStorageRoot*(db: ReadOnlyStateDB, address: EthAddress): Hash256 {.borrow.}
|
||||
|
@ -356,6 +356,11 @@ proc getMpt*(ldg: LedgerRef): CoreDxMptRef =
|
||||
result = ldg.ac.rawTrie.CoreDxAccRef.getMpt
|
||||
ldg.ifTrackApi: debug apiTxt, api, elapsed, result
|
||||
|
||||
proc getEthAccount*(ldg: LedgerRef, eAddr: EthAddress): Account =
|
||||
ldg.beginTrackApi LdgGetAthAccountFn
|
||||
result = ldg.ac.getEthAccount(eAddr)
|
||||
ldg.ifTrackApi: debug apiTxt, api, elapsed, result
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public virtual read-only methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -50,6 +50,7 @@ type
|
||||
LdgGetStorageFn = "getStorage"
|
||||
LdgGetStorageRootFn = "getStorageRoot"
|
||||
LdgGetTransientStorageFn = "getTransientStorage"
|
||||
LdgGetAthAccountFn = "getEthAccount"
|
||||
LdgInAccessListFn = "inAccessList"
|
||||
LdgIncNonceFn = "incNonce"
|
||||
LdgIsDeadAccountFn = "isDeadAccount"
|
||||
|
@ -1,35 +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.
|
||||
|
||||
## Read only source, import `state_db/read_write` for full functionality.
|
||||
##
|
||||
## Note that the writable mode is only partially supported by the `Aristo`
|
||||
## backend of `CoreDb` (read-only mode is fully supported.)
|
||||
|
||||
import
|
||||
state_db/[base, read_only]
|
||||
|
||||
export
|
||||
AccountStateDB,
|
||||
ReadOnlyStateDB,
|
||||
accountExists,
|
||||
contractCollision,
|
||||
db,
|
||||
getAccount,
|
||||
getBalance,
|
||||
getCode,
|
||||
getCodeHash,
|
||||
getNonce,
|
||||
getStorage,
|
||||
getStorageRoot,
|
||||
isDeadAccount,
|
||||
isEmptyAccount,
|
||||
newAccountStateDB,
|
||||
rootHash,
|
||||
to
|
||||
|
||||
# End
|
@ -1,314 +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.
|
||||
|
||||
import
|
||||
std/[sets, strformat, typetraits],
|
||||
chronicles,
|
||||
eth/[common, rlp, trie/trie_defs],
|
||||
results,
|
||||
../../constants,
|
||||
../../utils/utils,
|
||||
".."/[core_db, ledger, storage_types]
|
||||
|
||||
logScope:
|
||||
topics = "state_db"
|
||||
|
||||
# aleth/geth/parity compatibility mode:
|
||||
#
|
||||
# affected test cases both in GST and BCT:
|
||||
# - stSStoreTest\InitCollision.json
|
||||
# - stRevertTest\RevertInCreateInInit.json
|
||||
# - stCreate2\RevertInCreateInInitCreate2.json
|
||||
#
|
||||
# pyEVM sided with original Nimbus EVM
|
||||
#
|
||||
# implementation difference:
|
||||
# Aleth/geth/parity using accounts cache.
|
||||
# When contract creation happened on an existing
|
||||
# but 'empty' account with non empty storage will
|
||||
# get new empty storage root.
|
||||
# Aleth cs. only clear the storage cache while both pyEVM
|
||||
# and Nimbus will modify the state trie.
|
||||
# During the next SSTORE call, aleth cs. calculate
|
||||
# gas used based on this cached 'original storage value'.
|
||||
# In other hand pyEVM and Nimbus will fetch
|
||||
# 'original storage value' from state trie.
|
||||
#
|
||||
# Both Yellow Paper and EIP2200 are not clear about this
|
||||
# situation but since aleth/geth/and parity implement this
|
||||
# behaviour, we perhaps also need to implement it.
|
||||
#
|
||||
# TODO: should this compatibility mode enabled via
|
||||
# compile time switch, runtime switch, or just hard coded
|
||||
# it?
|
||||
const
|
||||
aleth_compat = true
|
||||
|
||||
type
|
||||
AccountStateDB* = ref object
|
||||
trie: AccountLedger
|
||||
originalRoot: KeccakHash # will be updated for every transaction
|
||||
when aleth_compat:
|
||||
cleared: HashSet[EthAddress]
|
||||
|
||||
#MptNodeRlpBytes* = seq[byte]
|
||||
#AccountProof* = seq[MptNodeRlpBytes]
|
||||
#SlotProof* = seq[MptNodeRlpBytes]
|
||||
|
||||
proc db*(db: AccountStateDB): CoreDbRef =
|
||||
db.trie.db
|
||||
|
||||
proc rootHash*(db: AccountStateDB): KeccakHash =
|
||||
db.trie.state
|
||||
|
||||
proc `rootHash=`*(db: AccountStateDB, root: KeccakHash) =
|
||||
db.trie = AccountLedger.init(db.trie.db, root)
|
||||
|
||||
func newCoreDbAccount(
|
||||
eAddr: EthAddress;
|
||||
nonce = AccountNonce(0);
|
||||
balance = 0.u256;
|
||||
): CoreDbAccount =
|
||||
CoreDbAccount(
|
||||
address: eAddr,
|
||||
nonce: nonce,
|
||||
balance: balance,
|
||||
codeHash: EMPTY_CODE_HASH)
|
||||
|
||||
proc newAccountStateDB*(backingStore: CoreDbRef,
|
||||
root: KeccakHash): AccountStateDB =
|
||||
result.new()
|
||||
result.trie = AccountLedger.init(backingStore, root)
|
||||
result.originalRoot = root
|
||||
when aleth_compat:
|
||||
result.cleared = HashSet[EthAddress]()
|
||||
|
||||
#proc getTrie*(db: AccountStateDB): CoreDxMptRef =
|
||||
# db.trie.mpt
|
||||
|
||||
#proc getSecureTrie*(db: AccountStateDB): CoreDbPhkRef =
|
||||
# db.trie.phk
|
||||
|
||||
proc to*(acc: CoreDbAccount; T: type Account): T =
|
||||
## Convert to legacy object, will throw an aseert if that fails
|
||||
let rc = acc.recast()
|
||||
if rc.isErr:
|
||||
raiseAssert "getAccount(): cannot convert account: " & $$rc.error
|
||||
rc.value
|
||||
|
||||
proc getAccount*(db: AccountStateDB, eAddr: EthAddress): CoreDbAccount =
|
||||
db.trie.fetch(eAddr).valueOr:
|
||||
return newCoreDbAccount(eAddr)
|
||||
|
||||
proc setAccount*(db: AccountStateDB, acc: CoreDbAccount) =
|
||||
db.trie.merge(acc)
|
||||
|
||||
proc deleteAccount*(db: AccountStateDB, acc: CoreDbAccount) =
|
||||
db.trie.delete(acc.address)
|
||||
|
||||
proc deleteAccount*(db: AccountStateDB, eAddr: EthAddress) =
|
||||
db.trie.delete(eAddr)
|
||||
|
||||
proc getCodeHash*(db: AccountStateDB, eAddr: EthAddress): Hash256 =
|
||||
db.getAccount(eAddr).codeHash
|
||||
|
||||
proc getBalance*(db: AccountStateDB, eAddr: EthAddress): UInt256 =
|
||||
db.getAccount(eAddr).balance
|
||||
|
||||
proc setBalance*(db: AccountStateDB, eAddr: EthAddress, balance: UInt256) =
|
||||
var acc = db.getAccount(eAddr)
|
||||
if acc.balance != balance:
|
||||
acc.balance = balance
|
||||
db.setAccount(acc)
|
||||
|
||||
proc addBalance*(db: AccountStateDB, eAddr: EthAddress, delta: UInt256) =
|
||||
db.setBalance(eAddr, db.getBalance(eAddr) + delta)
|
||||
|
||||
#template getStorageTrie(db: AccountStateDB, account: Account): auto =
|
||||
# storageTrieForAccount(db.trie, account)
|
||||
|
||||
proc subBalance*(db: AccountStateDB, eAddr: EthAddress, delta: UInt256) =
|
||||
db.setBalance(eAddr, db.getBalance(eAddr) - delta)
|
||||
|
||||
#template createTrieKeyFromSlot(slot: UInt256): auto =
|
||||
# # Converts a number to hex big-endian representation including
|
||||
# # prefix and leading zeros:
|
||||
# slot.toBytesBE
|
||||
# # Original py-evm code:
|
||||
# # pad32(int_to_big_endian(slot))
|
||||
# # morally equivalent to toByteRange_Unnecessary but with different types
|
||||
|
||||
proc clearStorage*(db: AccountStateDB, eAddr: EthAddress) =
|
||||
# Flush associated storage trie (will update account record on disk)
|
||||
db.trie.distinctBase.stoDelete(eAddr).isOkOr:
|
||||
raiseAssert "clearStorage(): stoDelete() failed, " & $$error
|
||||
# Reset storage info locally so that `Aristo` would not complain when
|
||||
# updating the account record on disk
|
||||
var account = db.getAccount(eAddr)
|
||||
account.storage = CoreDbColRef(nil)
|
||||
when aleth_compat:
|
||||
db.cleared.incl eAddr
|
||||
|
||||
proc getStorageRoot*(db: AccountStateDB, eAddr: EthAddress): Hash256 =
|
||||
db.getAccount(eAddr).storage.state.valueOr:
|
||||
EMPTY_ROOT_HASH
|
||||
|
||||
proc setStorage*(
|
||||
db: AccountStateDB;
|
||||
eAddr: EthAddress;
|
||||
slot: UInt256;
|
||||
value: UInt256;
|
||||
) =
|
||||
var
|
||||
acc = db.getAccount(eAddr)
|
||||
sto = StorageLedger.init(db.trie, acc)
|
||||
|
||||
if value > 0:
|
||||
sto.merge(slot, rlp.encode(value))
|
||||
else:
|
||||
sto.delete(slot)
|
||||
|
||||
# map slot hash back to slot value
|
||||
# see iterator storage below
|
||||
var
|
||||
# slotHash can be obtained from storage.merge()?
|
||||
slotHash = keccakHash(slot.toBytesBE)
|
||||
db.db.newKvt().put(
|
||||
slotHashToSlotKey(slotHash.data).toOpenArray, rlp.encode(slot)).isOkOr:
|
||||
raiseAssert "setStorage(): put(slotHash) failed: " & $$error
|
||||
|
||||
# Changing the storage trie might also change the `storage` descriptor when
|
||||
# the trie changes from empty to existing or v.v.
|
||||
acc.storage = sto.getColumn()
|
||||
|
||||
# No need to hold descriptors for longer than needed
|
||||
let state = acc.storage.state.valueOr:
|
||||
raiseAssert "Storage column state error: " & $$error
|
||||
if state == EMPTY_ROOT_HASH:
|
||||
acc.storage = CoreDbColRef(nil)
|
||||
|
||||
iterator storage*(db: AccountStateDB, eAddr: EthAddress): (UInt256, UInt256) =
|
||||
let kvt = db.db.newKvt()
|
||||
for key, value in db.trie.storage db.getAccount(eAddr):
|
||||
if key.len != 0:
|
||||
var keyData = kvt.get(slotHashToSlotKey(key).toOpenArray).valueOr:
|
||||
raiseAssert "storage(): get() failed: " & $$error
|
||||
yield (rlp.decode(keyData, UInt256), rlp.decode(value, UInt256))
|
||||
|
||||
proc getStorage*(
|
||||
db: AccountStateDB;
|
||||
eAddr: EthAddress;
|
||||
slot: UInt256;
|
||||
): Result[UInt256,void] =
|
||||
let
|
||||
acc = db.getAccount(eAddr)
|
||||
data = ? StorageLedger.init(db.trie, acc).fetch(slot)
|
||||
ok rlp.decode(data, UInt256)
|
||||
|
||||
proc setNonce*(db: AccountStateDB, eAddr: EthAddress; nonce: AccountNonce) =
|
||||
var acc = db.getAccount(eAddr)
|
||||
if nonce != acc.nonce:
|
||||
acc.nonce = nonce
|
||||
db.setAccount(acc)
|
||||
|
||||
proc getNonce*(db: AccountStateDB, eAddr: EthAddress): AccountNonce =
|
||||
db.getAccount(eAddr).nonce
|
||||
|
||||
proc incNonce*(db: AccountStateDB, eAddr: EthAddress) {.inline.} =
|
||||
db.setNonce(eAddr, db.getNonce(eAddr) + 1)
|
||||
|
||||
proc setCode*(db: AccountStateDB, eAddr: EthAddress, code: openArray[byte]) =
|
||||
var acc = db.getAccount(eAddr)
|
||||
let codeHash = keccakHash(code)
|
||||
if acc.codeHash != codeHash:
|
||||
if code.len != 0:
|
||||
db.db.newKvt().put(contractHashKey(codeHash).toOpenArray, code).isOkOr:
|
||||
raiseAssert "setCode(): put() failed: " & $$error
|
||||
acc.codeHash = codeHash
|
||||
db.setAccount(acc)
|
||||
|
||||
proc getCode*(db: AccountStateDB, eAddr: EthAddress): seq[byte] =
|
||||
let codeHash = db.getCodeHash(eAddr)
|
||||
db.db.newKvt().get(contractHashKey(codeHash).toOpenArray).valueOr:
|
||||
EmptyBlob
|
||||
|
||||
proc contractCollision*(db: AccountStateDB, eAddr: EthAddress): bool =
|
||||
db.getNonce(eAddr) != 0 or
|
||||
db.getCodeHash(eAddr) != EMPTY_CODE_HASH or
|
||||
db.getStorageRoot(eAddr) != EMPTY_ROOT_HASH
|
||||
|
||||
proc dumpAccount*(db: AccountStateDB, eAddr: string): string =
|
||||
let pAddr = eAddr.parseAddress
|
||||
return fmt"{eAddr}: Storage: {db.getStorage(pAddr, 0.u256)}; getAccount: {db.getAccount pAddr}"
|
||||
|
||||
proc accountExists*(db: AccountStateDB, eAddr: EthAddress): bool =
|
||||
db.trie.fetch(eAddr).isOk
|
||||
|
||||
proc isEmptyAccount*(db: AccountStateDB, eAddr: EthAddress): bool =
|
||||
let acc = db.trie.fetch(eAddr).valueOr:
|
||||
return false
|
||||
acc.nonce == 0 and
|
||||
acc.balance.isZero and
|
||||
acc.codeHash == EMPTY_CODE_HASH
|
||||
|
||||
proc isDeadAccount*(db: AccountStateDB, eAddr: EthAddress): bool =
|
||||
let acc = db.trie.fetch(eAddr).valueOr:
|
||||
return true
|
||||
acc.nonce == 0 and
|
||||
acc.balance.isZero and
|
||||
acc.codeHash == EMPTY_CODE_HASH
|
||||
|
||||
#proc removeEmptyRlpNode(branch: var seq[MptNodeRlpBytes]) =
|
||||
# if branch.len() == 1 and branch[0] == emptyRlp:
|
||||
# branch.del(0)
|
||||
|
||||
#proc getAccountProof*(db: AccountStateDB, eAddr: EthAddress): AccountProof =
|
||||
# var branch = db.trie.phk().getBranch(eAddr)
|
||||
# removeEmptyRlpNode(branch)
|
||||
# branch
|
||||
|
||||
#proc getStorageProof*(db: AccountStateDB, eAddr: EthAddress, slots: seq[UInt256]): seq[SlotProof] =
|
||||
# var acc = db.getAccount(eAddr)
|
||||
# var storageTrie = StorageLedger.init(db.trie, acc)
|
||||
#
|
||||
# var slotProofs = newSeqOfCap[SlotProof](slots.len())
|
||||
# for slot in slots:
|
||||
# var branch = storageTrie.phk().getBranch(createTrieKeyFromSlot(slot))
|
||||
# removeEmptyRlpNode(branch)
|
||||
# slotProofs.add(branch)
|
||||
#
|
||||
# slotProofs
|
||||
|
||||
# Note: `state_db.getCommittedStorage()` is nowhere used.
|
||||
#
|
||||
#proc getCommittedStorage*(db: AccountStateDB, eAddr: EthAddress, slot: UInt256): UInt256 =
|
||||
# let tmpHash = db.rootHash
|
||||
# db.rootHash = db.originalRoot
|
||||
# db.transactionID.shortTimeReadOnly():
|
||||
# when aleth_compat:
|
||||
# if eAddr in db.cleared:
|
||||
# debug "Forced contract creation on existing account detected", eAddr
|
||||
# result = 0.u256
|
||||
# else:
|
||||
# result = db.getStorage(eAddr, slot)[0]
|
||||
# else:
|
||||
# result = db.getStorage(eAddr, slot)[0]
|
||||
# db.rootHash = tmpHash
|
||||
|
||||
# Note: `state_db.updateOriginalRoot()` is nowhere used.
|
||||
#
|
||||
#proc updateOriginalRoot*(db: AccountStateDB) =
|
||||
# ## this proc will be called for every transaction
|
||||
# db.originalRoot = db.rootHash
|
||||
# # no need to rollback or dispose
|
||||
# # transactionID, it will be handled elsewhere
|
||||
# db.transactionID = db.db.getTransactionID()
|
||||
#
|
||||
# when aleth_compat:
|
||||
# db.cleared.clear()
|
||||
|
||||
# End
|
@ -1,37 +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.
|
||||
|
||||
import
|
||||
results,
|
||||
../core_db,
|
||||
./base
|
||||
|
||||
type
|
||||
ReadOnlyStateDB* = distinct AccountStateDB
|
||||
|
||||
#proc getTrie*(db: ReadOnlyStateDB): CoreDbMptRef {.borrow.}
|
||||
proc db*(db: ReadOnlyStateDB): CoreDbRef {.borrow.}
|
||||
proc rootHash*(db: ReadOnlyStateDB): KeccakHash {.borrow.}
|
||||
proc getAccount*(db: ReadOnlyStateDB, address: EthAddress): CoreDbAccount {.borrow.}
|
||||
proc getCodeHash*(db: ReadOnlyStateDB, address: EthAddress): Hash256 {.borrow.}
|
||||
proc getBalance*(db: ReadOnlyStateDB, address: EthAddress): UInt256 {.borrow.}
|
||||
proc getStorageRoot*(db: ReadOnlyStateDB, address: EthAddress): Hash256 {.borrow.}
|
||||
proc getStorage*(db: ReadOnlyStateDB, address: EthAddress, slot: UInt256): Result[UInt256,void] {.borrow.}
|
||||
proc getNonce*(db: ReadOnlyStateDB, address: EthAddress): AccountNonce {.borrow.}
|
||||
proc getCode*(db: ReadOnlyStateDB, address: EthAddress): seq[byte] {.borrow.}
|
||||
proc contractCollision*(db: ReadOnlyStateDB, address: EthAddress): bool {.borrow.}
|
||||
proc accountExists*(db: ReadOnlyStateDB, address: EthAddress): bool {.borrow.}
|
||||
proc isDeadAccount*(db: ReadOnlyStateDB, address: EthAddress): bool {.borrow.}
|
||||
proc isEmptyAccount*(db: ReadOnlyStateDB, address: EthAddress): bool {.borrow.}
|
||||
#proc getAccountProof*(db: ReadOnlyStateDB, address: EthAddress): AccountProof {.borrow.}
|
||||
#proc getStorageProof*(db: ReadOnlyStateDB, address: EthAddress, slots: seq[UInt256]): seq[SlotProof] {.borrow.}
|
||||
#proc getCommittedStorage*(db: ReadOnlyStateDB, address: EthAddress, slot: UInt256): UInt256 {.borrow.}
|
||||
|
||||
# End
|
@ -1,17 +0,0 @@
|
||||
# Nimbus
|
||||
# Copyright (c) 2018-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
|
||||
"."/[base, read_only]
|
||||
|
||||
export
|
||||
base, read_only
|
||||
|
||||
# End
|
@ -15,7 +15,7 @@ import
|
||||
graphql, graphql/graphql as context,
|
||||
graphql/common/types, graphql/httpserver,
|
||||
graphql/instruments/query_complexity,
|
||||
../db/[state_db],
|
||||
../db/[ledger],
|
||||
../rpc/rpc_types,
|
||||
../rpc/rpc_utils,
|
||||
".."/[transaction, vm_state, config, constants],
|
||||
@ -47,7 +47,7 @@ type
|
||||
AccountNode = ref object of Node
|
||||
address: EthAddress
|
||||
account: Account
|
||||
db: ReadOnlyStateDB
|
||||
db: LedgerRef
|
||||
|
||||
TxNode = ref object of Node
|
||||
tx: Transaction
|
||||
@ -99,7 +99,7 @@ proc headerNode(ctx: GraphqlContextRef, header: common.BlockHeader): Node =
|
||||
header: header
|
||||
)
|
||||
|
||||
proc accountNode(ctx: GraphqlContextRef, acc: Account, address: EthAddress, db: ReadOnlyStateDB): Node =
|
||||
proc accountNode(ctx: GraphqlContextRef, acc: Account, address: EthAddress, db: LedgerRef): Node =
|
||||
AccountNode(
|
||||
kind: nkMap,
|
||||
typeName: ctx.ids[ethAccount],
|
||||
@ -146,11 +146,10 @@ proc wdNode(ctx: GraphqlContextRef, wd: Withdrawal): Node =
|
||||
wd: wd
|
||||
)
|
||||
|
||||
proc getStateDB(com: CommonRef, header: common.BlockHeader): ReadOnlyStateDB =
|
||||
proc getStateDB(com: CommonRef, header: common.BlockHeader): LedgerRef =
|
||||
## 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)
|
||||
ReadOnlyStateDB(ac)
|
||||
LedgerRef.init(com.db, header.stateRoot)
|
||||
|
||||
proc getBlockByNumber(ctx: GraphqlContextRef, number: Node): RespResult =
|
||||
try:
|
||||
@ -353,8 +352,8 @@ proc accountNode(ctx: GraphqlContextRef, header: common.BlockHeader, address: Et
|
||||
# but hive test case demand something
|
||||
if not db.accountExists(address):
|
||||
return ok(respNull())
|
||||
let acc = db.getAccount(address)
|
||||
ok(accountNode(ctx, acc.to(Account), address, db))
|
||||
let acc = db.getEthAccount(address)
|
||||
ok(accountNode(ctx, acc, address, db))
|
||||
except RlpError as ex:
|
||||
err(ex.msg)
|
||||
|
||||
@ -552,7 +551,7 @@ proc accountStorage(ud: RootRef, params: Args, parent: Node): RespResult {.apiPr
|
||||
let acc = AccountNode(parent)
|
||||
try:
|
||||
let slot = parse(params[0].val.stringVal, UInt256, radix = 16)
|
||||
let val = acc.db.getStorage(acc.address, slot).valueOr: 0.u256
|
||||
let val = acc.db.getStorage(acc.address, slot)
|
||||
byte32Node(val)
|
||||
except RlpError as ex:
|
||||
err(ex.msg)
|
||||
|
@ -14,7 +14,6 @@ import
|
||||
json_rpc/rpcserver, stint, web3/conversions,
|
||||
eth/p2p,
|
||||
../[transaction, vm_state, constants, vm_types],
|
||||
../db/state_db,
|
||||
rpc_types, rpc_utils,
|
||||
../common/common,
|
||||
../utils/utils,
|
||||
@ -27,13 +26,12 @@ import
|
||||
|
||||
type
|
||||
BlockHeader = eth_types.BlockHeader
|
||||
ReadOnlyStateDB = state_db.ReadOnlyStateDB
|
||||
|
||||
proc getMultiKeys*(
|
||||
com: CommonRef,
|
||||
blockHeader: BlockHeader,
|
||||
statePostExecution: bool): MultiKeysRef
|
||||
{.raises: [RlpError, BlockNotFound, ValueError, CatchableError].} =
|
||||
{.raises: [RlpError, BlockNotFound, ValueError].} =
|
||||
|
||||
let
|
||||
chainDB = com.db
|
||||
@ -60,8 +58,8 @@ proc getMultiKeys*(
|
||||
mkeys
|
||||
|
||||
proc getBlockProofs*(
|
||||
accDB: ReadOnlyStateDB,
|
||||
mkeys: MultiKeysRef): seq[ProofResponse] {.raises: [RlpError].} =
|
||||
accDB: LedgerRef,
|
||||
mkeys: MultiKeysRef): seq[ProofResponse] =
|
||||
|
||||
var blockProofs = newSeq[ProofResponse]()
|
||||
|
||||
@ -81,11 +79,10 @@ proc setupExpRpc*(com: CommonRef, server: RpcServer) =
|
||||
|
||||
let chainDB = com.db
|
||||
|
||||
proc getStateDB(header: BlockHeader): ReadOnlyStateDB =
|
||||
proc getStateDB(header: BlockHeader): LedgerRef =
|
||||
## 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)
|
||||
result = ReadOnlyStateDB(ac)
|
||||
LedgerRef.init(chainDB, header.stateRoot)
|
||||
|
||||
server.rpc("exp_getProofsByBlockNumber") do(quantityTag: BlockTag, statePostExecution: bool) -> seq[ProofResponse]:
|
||||
## Returns the block proofs for a block by block number or tag.
|
||||
|
@ -16,7 +16,7 @@ import
|
||||
eth/common/eth_types_json_serialization,
|
||||
eth/[keys, rlp, p2p],
|
||||
".."/[transaction, vm_state, constants],
|
||||
../db/state_db,
|
||||
../db/ledger,
|
||||
./rpc_types, ./rpc_utils, ./oracle,
|
||||
../transaction/call_evm,
|
||||
../core/tx_pool,
|
||||
@ -42,23 +42,23 @@ when not AccountAndStorageProofAvailableAndWorking:
|
||||
AccountProof = seq[MptNodeRlpBytes]
|
||||
SlotProof = seq[MptNodeRlpBytes]
|
||||
func getAccountProof(
|
||||
db: ReadOnlyStateDB;
|
||||
db: LedgerRef;
|
||||
eAddr: EthAddress;
|
||||
): AccountProof =
|
||||
discard
|
||||
func getStorageProof(
|
||||
db: ReadOnlyStateDB;
|
||||
db: LedgerRef;
|
||||
eAddr: EthAddress;
|
||||
slot: seq[UInt256];
|
||||
): seq[SlotProof] =
|
||||
discard
|
||||
|
||||
proc getProof*(
|
||||
accDB: ReadOnlyStateDB,
|
||||
accDB: LedgerRef,
|
||||
address: EthAddress,
|
||||
slots: seq[UInt256]): ProofResponse {.raises: [RlpError].} =
|
||||
slots: seq[UInt256]): ProofResponse =
|
||||
let
|
||||
acc = accDB.getAccount(address)
|
||||
acc = accDB.getEthAccount(address)
|
||||
accExists = accDB.accountExists(address)
|
||||
accountProof = accDB.getAccountProof(address)
|
||||
slotProofs = accDB.getStorageProof(address, slots)
|
||||
@ -66,7 +66,7 @@ proc getProof*(
|
||||
var storage = newSeqOfCap[StorageProof](slots.len)
|
||||
|
||||
for i, slotKey in slots:
|
||||
let slotValue = accDB.getStorage(address, slotKey).valueOr: 0.u256
|
||||
let slotValue = accDB.getStorage(address, slotKey)
|
||||
storage.add(StorageProof(
|
||||
key: slotKey,
|
||||
value: slotValue,
|
||||
@ -79,7 +79,7 @@ proc getProof*(
|
||||
balance: acc.balance,
|
||||
nonce: w3Qty(acc.nonce),
|
||||
codeHash: w3Hash(acc.codeHash),
|
||||
storageHash: w3Hash(acc.to(Account).storageRoot),
|
||||
storageHash: w3Hash(acc.storageRoot),
|
||||
storageProof: storage)
|
||||
else:
|
||||
ProofResponse(
|
||||
@ -92,13 +92,12 @@ proc setupEthRpc*(
|
||||
txPool: TxPoolRef, oracle: Oracle, server: RpcServer) =
|
||||
|
||||
let chainDB = com.db
|
||||
proc getStateDB(header: BlockHeader): ReadOnlyStateDB =
|
||||
proc getStateDB(header: BlockHeader): LedgerRef =
|
||||
## 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)
|
||||
result = ReadOnlyStateDB(ac)
|
||||
LedgerRef.init(chainDB, header.stateRoot)
|
||||
|
||||
proc stateDBFromTag(quantityTag: BlockTag, readOnly = true): ReadOnlyStateDB
|
||||
proc stateDBFromTag(quantityTag: BlockTag, readOnly = true): LedgerRef
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
result = getStateDB(chainDB.headerFromTag(quantityTag))
|
||||
|
||||
@ -182,7 +181,7 @@ proc setupEthRpc*(
|
||||
let
|
||||
accDB = stateDBFromTag(quantityTag)
|
||||
address = data.ethAddr
|
||||
data = accDB.getStorage(address, slot).valueOr: 0.u256
|
||||
data = accDB.getStorage(address, slot)
|
||||
result = data.w3FixedBytes
|
||||
|
||||
server.rpc("eth_getTransactionCount") do(data: Web3Address, quantityTag: BlockTag) -> Web3Quantity:
|
||||
|
@ -16,7 +16,7 @@ import
|
||||
./test_helpers, ./test_allowed_to_fail,
|
||||
../premix/parser, test_config,
|
||||
../nimbus/[vm_state, vm_types, errors, constants],
|
||||
../nimbus/db/[ledger, state_db],
|
||||
../nimbus/db/ledger,
|
||||
../nimbus/utils/[utils, debug],
|
||||
../nimbus/evm/tracer/legacy_tracer,
|
||||
../nimbus/evm/tracer/json_tracer,
|
||||
@ -187,8 +187,8 @@ proc testGetMultiKeys(chain: ChainRef, parentHeader, currentHeader: BlockHeader)
|
||||
|
||||
# use the MultiKeysRef to build the block proofs
|
||||
let
|
||||
ac = newAccountStateDB(chain.com.db, currentHeader.stateRoot)
|
||||
blockProofs = getBlockProofs(state_db.ReadOnlyStateDB(ac), mkeys)
|
||||
ac = LedgerRef.init(chain.com.db, currentHeader.stateRoot)
|
||||
blockProofs = getBlockProofs(ac, mkeys)
|
||||
if blockProofs.len() != 0:
|
||||
raise newException(ValidationError, "Expected blockProofs.len() == 0")
|
||||
|
||||
|
@ -12,14 +12,12 @@ import
|
||||
web3/eth_api,
|
||||
nimcrypto/[keccak, hash],
|
||||
eth/[common, rlp, keys, trie/trie_defs, trie/hexary_proof_verification],
|
||||
../nimbus/db/state_db,
|
||||
../nimbus/db/[ledger, core_db],
|
||||
../nimbus/common/chain_config,
|
||||
../nimbus/rpc/p2p
|
||||
|
||||
type
|
||||
Hash256 = eth_types.Hash256
|
||||
ReadOnlyStateDB = state_db.ReadOnlyStateDB
|
||||
|
||||
func ethAddr*(x: Address): EthAddress =
|
||||
EthAddress x
|
||||
@ -79,7 +77,7 @@ proc setupStateDB(genAccounts: GenesisAlloc, stateDB: LedgerRef): Hash256 =
|
||||
|
||||
proc checkProofsForExistingLeafs(
|
||||
genAccounts: GenesisAlloc,
|
||||
accDB: ReadOnlyStateDB,
|
||||
accDB: LedgerRef,
|
||||
stateRoot: Hash256) =
|
||||
|
||||
for address, account in genAccounts:
|
||||
@ -106,7 +104,7 @@ proc checkProofsForExistingLeafs(
|
||||
|
||||
proc checkProofsForMissingLeafs(
|
||||
genAccounts: GenesisAlloc,
|
||||
accDB: ReadOnlyStateDB,
|
||||
accDB: LedgerRef,
|
||||
stateRoot: Hash256) =
|
||||
|
||||
let
|
||||
@ -137,10 +135,9 @@ proc getProofJsonMain*() =
|
||||
coreDb = newCoreDbRef(DefaultDbMemory)
|
||||
accountsCache = LedgerRef.init(coreDb, emptyRlpHash)
|
||||
stateRootHash = setupStateDB(accounts, accountsCache)
|
||||
accountDb = newAccountStateDB(coreDb, stateRootHash)
|
||||
readOnlyDb = ReadOnlyStateDB(accountDb)
|
||||
accountDb = LedgerRef.init(coreDb, stateRootHash)
|
||||
|
||||
checkProofsForExistingLeafs(accounts, readOnlyDb, stateRootHash)
|
||||
checkProofsForExistingLeafs(accounts, accountDb, stateRootHash)
|
||||
|
||||
test "Get proofs for missing leafs":
|
||||
for file in genesisFiles:
|
||||
@ -150,10 +147,9 @@ proc getProofJsonMain*() =
|
||||
coreDb = newCoreDbRef(DefaultDbMemory)
|
||||
accountsCache = LedgerRef.init(coreDb, emptyRlpHash)
|
||||
stateRootHash = setupStateDB(accounts, accountsCache)
|
||||
accountDb = newAccountStateDB(coreDb, stateRootHash)
|
||||
readOnlyDb = ReadOnlyStateDB(accountDb)
|
||||
accountDb = LedgerRef.init(coreDb, stateRootHash)
|
||||
|
||||
checkProofsForMissingLeafs(accounts, readOnlyDb, stateRootHash)
|
||||
checkProofsForMissingLeafs(accounts, accountDb, stateRootHash)
|
||||
|
||||
when isMainModule:
|
||||
getProofJsonMain()
|
||||
|
@ -33,7 +33,7 @@ import
|
||||
../nimbus/db/opts,
|
||||
../nimbus/db/core_db,
|
||||
../nimbus/db/core_db/persistent,
|
||||
../nimbus/db/state_db/base,
|
||||
../nimbus/db/ledger,
|
||||
./rpc/experimental_rpc_client
|
||||
|
||||
const
|
||||
@ -53,7 +53,7 @@ template toHash256(hash: untyped): Hash256 =
|
||||
fromHex(Hash256, hash.toHex())
|
||||
|
||||
proc updateStateUsingProofsAndCheckStateRoot(
|
||||
stateDB: AccountStateDB,
|
||||
stateDB: LedgerRef,
|
||||
expectedStateRoot: Hash256,
|
||||
proofs: seq[ProofResponse]) =
|
||||
|
||||
@ -125,7 +125,7 @@ proc rpcGetProofsTrackStateChangesMain*() =
|
||||
|
||||
let
|
||||
blockHeader = waitFor client.eth_getBlockByNumber(blockId(START_BLOCK), false)
|
||||
stateDB = newAccountStateDB(com.db, blockHeader.stateRoot.toHash256())
|
||||
stateDB = LedgerRef.init(com.db, blockHeader.stateRoot.toHash256())
|
||||
|
||||
for i in START_BLOCK..END_BLOCK:
|
||||
let
|
||||
|
Loading…
x
Reference in New Issue
Block a user