2018-01-29 17:40:22 +00:00
|
|
|
import
|
|
|
|
strformat, tables,
|
2018-02-20 17:27:43 +00:00
|
|
|
../constants, ../errors, ../validation, ../account, ../logging, ../utils_numeric, .. / utils / [padding, bytes, keccak], ttmath, rlp
|
2018-01-29 17:40:22 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
AccountStateDB* = ref object
|
2018-02-20 17:27:43 +00:00
|
|
|
db*: Table[string, UInt256]
|
2018-02-13 17:18:08 +00:00
|
|
|
rootHash*: string # TODO trie
|
2018-01-29 17:40:22 +00:00
|
|
|
|
2018-02-13 17:18:08 +00:00
|
|
|
proc newAccountStateDB*(db: Table[string, string], readOnly: bool = false): AccountStateDB =
|
2018-02-20 17:27:43 +00:00
|
|
|
result = AccountStateDB(db: initTable[string, UInt256]())
|
2018-01-29 17:40:22 +00:00
|
|
|
|
|
|
|
proc logger*(db: AccountStateDB): Logger =
|
|
|
|
logging.getLogger("db.State")
|
|
|
|
|
2018-01-31 12:57:05 +00:00
|
|
|
proc getAccount(db: AccountStateDB, address: string): Account =
|
2018-01-29 17:40:22 +00:00
|
|
|
# let rlpAccount = db.trie[address]
|
|
|
|
# if not rlpAccount.isNil:
|
|
|
|
# account = rlp.decode[Account](rlpAccount)
|
|
|
|
# account.mutable = true
|
|
|
|
# else:
|
|
|
|
# account = newAccount()
|
|
|
|
result = newAccount() # TODO
|
|
|
|
|
2018-01-31 12:57:05 +00:00
|
|
|
proc setAccount(db: AccountStateDB, address: string, account: Account) =
|
2018-01-29 17:40:22 +00:00
|
|
|
# db.trie[address] = rlp.encode[Account](account)
|
|
|
|
discard # TODO
|
|
|
|
|
2018-02-13 17:18:08 +00:00
|
|
|
|
|
|
|
proc getCodeHash*(db: AccountStateDB, address: string): string =
|
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
|
|
|
let account = db.getAccount(address)
|
|
|
|
result = account.codeHash
|
2018-01-29 17:40:22 +00:00
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc getBalance*(db: AccountStateDB, address: string): UInt256 =
|
2018-01-29 17:40:22 +00:00
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
|
|
|
let account = db.getAccount(address)
|
|
|
|
account.balance
|
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc setBalance*(db: var AccountStateDB, address: string, balance: UInt256) =
|
2018-01-29 17:40:22 +00:00
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
|
|
|
let account = db.getAccount(address)
|
|
|
|
account.balance = balance
|
|
|
|
db.setAccount(address, account)
|
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc deltaBalance*(db: var AccountStateDB, address: string, delta: UInt256) =
|
2018-01-29 17:40:22 +00:00
|
|
|
db.setBalance(address, db.getBalance(address) + delta)
|
|
|
|
|
2018-02-13 17:18:08 +00:00
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc setStorage*(db: var AccountStateDB, address: string, slot: UInt256, value: UInt256) =
|
|
|
|
#validateGte(value, 0, title="Storage Value")
|
|
|
|
#validateGte(slot, 0, title="Storage Slot")
|
2018-02-13 17:18:08 +00:00
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
2018-02-20 17:27:43 +00:00
|
|
|
|
2018-02-13 17:18:08 +00:00
|
|
|
# TODO
|
2018-02-20 17:27:43 +00:00
|
|
|
# let account = db.getAccount(address)
|
2018-02-13 17:18:08 +00:00
|
|
|
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
|
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
let slotAsKey = slot.intToBigEndian.pad32.toString
|
|
|
|
var storage = db.db
|
|
|
|
# TODO fix
|
|
|
|
#if value > 0:
|
|
|
|
# let encodedValue = rlp.encode(value)
|
|
|
|
# storage[slotAsKey] = encodedValue
|
|
|
|
#else:
|
|
|
|
# storage.del(slotAsKey)
|
|
|
|
storage[slotAsKey] = value
|
2018-02-13 17:18:08 +00:00
|
|
|
# account.storageRoot = storage.rootHash
|
|
|
|
# db.setAccount(address, account)
|
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc getStorage*(db: var AccountStateDB, address: string, slot: UInt256): UInt256 =
|
2018-02-13 17:18:08 +00:00
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
2018-02-20 17:27:43 +00:00
|
|
|
#validateGte(slot, 0, title="Storage Slot")
|
2018-02-13 17:18:08 +00:00
|
|
|
|
|
|
|
# TODO
|
2018-02-20 17:27:43 +00:00
|
|
|
# make it more correct
|
|
|
|
# for now, we just use a table
|
|
|
|
|
2018-02-13 17:18:08 +00:00
|
|
|
# let account = db.GetAccount(address)
|
|
|
|
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
|
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
let slotAsKey = slot.intToBigEndian.pad32.toString
|
|
|
|
var storage = db.db
|
|
|
|
if storage.hasKey(slotAsKey):
|
|
|
|
result = storage[slotAsKey]
|
|
|
|
#let encodedValue = storage[slotAsKey]
|
|
|
|
#result = rlp.decode(encodedValue)
|
|
|
|
else:
|
|
|
|
result = 0.u256
|
2018-02-13 17:18:08 +00:00
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc setNonce*(db: var AccountStateDB, address: string, nonce: UInt256) =
|
2018-02-13 17:18:08 +00:00
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
2018-02-20 17:27:43 +00:00
|
|
|
#validateGte(nonce, 0, title="Nonce")
|
2018-02-13 17:18:08 +00:00
|
|
|
|
|
|
|
var account = db.getAccount(address)
|
|
|
|
account.nonce = nonce
|
|
|
|
|
|
|
|
db.setAccount(address, account)
|
|
|
|
|
2018-02-20 17:27:43 +00:00
|
|
|
proc getNonce*(db: AccountStateDB, address: string): UInt256 =
|
2018-02-13 17:18:08 +00:00
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
|
|
|
|
|
|
|
let account = db.getAccount(address)
|
|
|
|
return account.nonce
|
|
|
|
|
|
|
|
proc setCode*(db: var AccountStateDB, address: string, code: string) =
|
|
|
|
validateCanonicalAddress(address, title="Storage Address")
|
|
|
|
|
|
|
|
var account = db.getAccount(address)
|
|
|
|
|
|
|
|
account.codeHash = keccak(code)
|
2018-02-20 17:27:43 +00:00
|
|
|
#db.db[account.codeHash] = code
|
2018-02-13 17:18:08 +00:00
|
|
|
db.setAccount(address, account)
|
|
|
|
|
|
|
|
proc getCode*(db: var AccountStateDB, address: string): string =
|
|
|
|
let codeHash = db.getCodeHash(address)
|
2018-02-20 17:27:43 +00:00
|
|
|
#if db.db.hasKey(codeHash):
|
|
|
|
# result = db.db[codeHash]
|
|
|
|
#else:
|
|
|
|
result = ""
|
2018-02-13 17:18:08 +00:00
|
|
|
|
|
|
|
# proc rootHash*(db: AccountStateDB): string =
|
|
|
|
# TODO return self.Trie.rootHash
|
|
|
|
|
|
|
|
# proc `rootHash=`*(db: var AccountStateDB, value: string) =
|
|
|
|
# TODO: self.Trie.rootHash = value
|