nimbus-eth1/nimbus/db/state_db.nim

133 lines
4.6 KiB
Nim

# Nimbus
# Copyright (c) 2018 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_common, tables, nimcrypto, stint, rlp,
../constants, ../errors, ../validation, ../account, ../logging
type
AccountStateDB* = ref object
db*: Table[string, BytesRange]
rootHash*: Hash256 # TODO trie
proc newAccountStateDB*(db: Table[string, string], readOnly: bool = false): AccountStateDB =
result = AccountStateDB(db: initTable[string, BytesRange]())
proc logger*(db: AccountStateDB): Logger =
logging.getLogger("db.State")
proc getAccount(db: AccountStateDB, address: EthAddress): Account =
# let rlpAccount = db.trie[address]
# if not rlpAccount.isNil:
# account = rlp.decode[Account](rlpAccount)
# account.mutable = true
# else:
# account = newAccount()
result = newAccount() # TODO
proc setAccount(db: AccountStateDB, address: EthAddress, account: Account) =
# db.trie[address] = rlp.encode[Account](account)
discard # TODO
proc getCodeHash*(db: AccountStateDB, address: EthAddress): Hash256 =
validateCanonicalAddress(address, title="Storage Address")
let account = db.getAccount(address)
result = account.codeHash
proc getBalance*(db: AccountStateDB, address: EthAddress): UInt256 =
validateCanonicalAddress(address, title="Storage Address")
let account = db.getAccount(address)
account.balance
proc setBalance*(db: var AccountStateDB, address: EthAddress, balance: UInt256) =
validateCanonicalAddress(address, title="Storage Address")
let account = db.getAccount(address)
account.balance = balance
db.setAccount(address, account)
proc deltaBalance*(db: var AccountStateDB, address: EthAddress, delta: UInt256) =
db.setBalance(address, db.getBalance(address) + delta)
proc setStorage*(db: var AccountStateDB, address: EthAddress, slot: UInt256, value: UInt256) =
#validateGte(value, 0, title="Storage Value")
#validateGte(slot, 0, title="Storage Slot")
validateCanonicalAddress(address, title="Storage Address")
# TODO
# let account = db.getAccount(address)
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
let slotAsKey = "0x" & slot.dumpHex # Convert to a number to hex big-endian representation including prefix and leading zeros
var storage = db.db
# TODO fix
if value > 0:
let encodedValue = rlp.encode value.toByteArrayBE
storage[slotAsKey] = encodedValue
else:
storage.del(slotAsKey)
#storage[slotAsKey] = value
# account.storageRoot = storage.rootHash
# db.setAccount(address, account)
proc getStorage*(db: var AccountStateDB, address: EthAddress, slot: UInt256): (UInt256, bool) =
validateCanonicalAddress(address, title="Storage Address")
#validateGte(slot, 0, title="Storage Slot")
# TODO
# make it more correct
# for now, we just use a table
# let account = db.GetAccount(address)
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
let slotAsKey = "0x" & slot.dumpHex # Convert to a number to hex big-endian representation including prefix and leading zeros
var storage = db.db
if storage.hasKey(slotAsKey):
let byteRange = storage[slotAsKey]
result = (readUintBE[256](byteRange.toOpenArray), true)
else:
result = (0.u256, false)
proc setNonce*(db: var AccountStateDB, address: EthAddress, nonce: UInt256) =
validateCanonicalAddress(address, title="Storage Address")
#validateGte(nonce, 0, title="Nonce")
var account = db.getAccount(address)
account.nonce = nonce
db.setAccount(address, account)
proc getNonce*(db: AccountStateDB, address: EthAddress): UInt256 =
validateCanonicalAddress(address, title="Storage Address")
let account = db.getAccount(address)
return account.nonce
proc setCode*(db: var AccountStateDB, address: EthAddress, code: string) =
validateCanonicalAddress(address, title="Storage Address")
var account = db.getAccount(address)
account.codeHash = keccak256.digest code
#db.db[account.codeHash] = code
db.setAccount(address, account)
proc getCode*(db: var AccountStateDB, address: EthAddress): string =
let codeHash = db.getCodeHash(address)
#if db.db.hasKey(codeHash):
# result = db.db[codeHash]
#else:
result = ""
# proc rootHash*(db: AccountStateDB): string =
# TODO return self.Trie.rootHash
# proc `rootHash=`*(db: var AccountStateDB, value: string) =
# TODO: self.Trie.rootHash = value