mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 21:34:33 +00:00
Port parts of several other modules
Focus on getting most types defined with minimal implementation and fields sufficient for simple tests
This commit is contained in:
parent
e1c04e587f
commit
84ccfc5966
10
src/block.nim
Normal file
10
src/block.nim
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import
|
||||||
|
logging, constants, utils/header
|
||||||
|
|
||||||
|
type
|
||||||
|
CountableList*[T] = ref object
|
||||||
|
elements: seq[T] # TODO
|
||||||
|
|
||||||
|
Block* = ref object of RootObj
|
||||||
|
header*: Header
|
||||||
|
uncles*: CountableList[Header]
|
60
src/chain.nim
Normal file
60
src/chain.nim
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import
|
||||||
|
tables,
|
||||||
|
logging, constants, errors, validation, utils / [hexadecimal]
|
||||||
|
|
||||||
|
type
|
||||||
|
BlockHeader* = ref object
|
||||||
|
# Placeholder TODO
|
||||||
|
|
||||||
|
Chain* = ref object
|
||||||
|
## An Chain is a combination of one or more VM classes. Each VM is associated
|
||||||
|
## with a range of blocks. The Chain class acts as a wrapper around these other
|
||||||
|
## VM classes, delegating operations to the appropriate VM depending on the
|
||||||
|
## current block number.
|
||||||
|
header*: BlockHeader
|
||||||
|
logger*: Logger
|
||||||
|
networkId*: cstring
|
||||||
|
vmsByRange*: seq[tuple[blockNumber: Int256, vm: VM]] # TODO
|
||||||
|
importBlock*: bool
|
||||||
|
validateBlock*: bool
|
||||||
|
db*: BaseChainDB
|
||||||
|
|
||||||
|
GenesisParams* = ref object
|
||||||
|
blockNumber*: Int256
|
||||||
|
difficulty*: Int256
|
||||||
|
gasLimit*: Int256
|
||||||
|
parentHash*: cstring
|
||||||
|
coinbase*: cstring
|
||||||
|
nonce: cstring
|
||||||
|
mixHash: cstring
|
||||||
|
extraData: cstring
|
||||||
|
timestamp: int,
|
||||||
|
stateRoot: cstring
|
||||||
|
|
||||||
|
FundedAddress* = ref object
|
||||||
|
balance*: Int256
|
||||||
|
nonce*: int
|
||||||
|
code*: cstring
|
||||||
|
|
||||||
|
|
||||||
|
proc configureChain*(name: string, blockNumber: Int256, vm: VM, importBlock: bool = true, validateBlock: bool = true): Chain =
|
||||||
|
new(result)
|
||||||
|
result.vmsByRange = @[(blockNumber: blockNumber, vm: vm)]
|
||||||
|
|
||||||
|
proc fromGenesis*(
|
||||||
|
chain: Chain,
|
||||||
|
chainDB: BaseChainDB,
|
||||||
|
genesisParams: GenesisParams,
|
||||||
|
genesisState: Table[string, FundedAddress]): Chain =
|
||||||
|
## Initialize the Chain from a genesis state
|
||||||
|
var stateDB = chaindb.getStateDB(BLANK_ROOT_HASH)
|
||||||
|
for account, accountData in genesisState:
|
||||||
|
stateDB.setBalance(account, accountData.balance)
|
||||||
|
stateDB.setNonce(account, accountData.nonce)
|
||||||
|
stateDB.setCode(account, accountData.code)
|
||||||
|
|
||||||
|
new(result)
|
||||||
|
result.db = chainDB
|
||||||
|
result.header = BlockHeader()
|
||||||
|
result.logger = logging.getLogger("evm.chain.chain.Chain")
|
||||||
|
chainDB.persistBlockToDB(result.getBlock())
|
@ -114,7 +114,7 @@ const
|
|||||||
UINT_256_CEILING* = (2 ^ X).Int256
|
UINT_256_CEILING* = (2 ^ X).Int256
|
||||||
UINT_255_MAX* = (2 ^ (X - 1) - 1).Int256
|
UINT_255_MAX* = (2 ^ (X - 1) - 1).Int256
|
||||||
UINT_255_CEILING* = (2 ^ (X - 1)).Int256
|
UINT_255_CEILING* = (2 ^ (X - 1)).Int256
|
||||||
NULLBYTE = cstring"\\x00"
|
NULLBYTE = cstring"\x00"
|
||||||
EMPTYWORD = repeat(NULLBYTE, 32)
|
EMPTYWORD = repeat(NULLBYTE, 32)
|
||||||
# UINT160CEILING = 2 ^ 160
|
# UINT160CEILING = 2 ^ 160
|
||||||
CREATE_CONTRACT_ADDRESS* = cstring""
|
CREATE_CONTRACT_ADDRESS* = cstring""
|
||||||
@ -190,15 +190,16 @@ const
|
|||||||
SECPK1Gx = 0
|
SECPK1Gx = 0
|
||||||
SECPK1Gy = 0
|
SECPK1Gy = 0
|
||||||
SECPK1G = (SECPK1Gx, SECPK1Gy)
|
SECPK1G = (SECPK1Gx, SECPK1Gy)
|
||||||
EMPTYUNCLEHASH = cstring"\\x1d\\xccM\\xe8\\xde\\xc7]z\\xab\\x85\\xb5g\\xb6\\xcc\\xd4\\x1a\\xd3\\x12E\\x1b\\x94\\x8at\\x13\\xf0\\xa1B\\xfd@\\xd4\\x93G"
|
EMPTYUNCLEHASH = cstring"\x1d\xccM\xe8\xde\xc7]z\xab\x85\xb5g\xb6\xcc\xd4\x1a\xd3\x12E\x1b\x94\x8at\x13\xf0\xa1B\xfd@\xd4\x93G"
|
||||||
GENESIS_BLOCK_NUMBER* = 0.Int256
|
GENESIS_BLOCK_NUMBER* = 0.Int256
|
||||||
GENESIS_DIFFICULTY* = 131072.Int256
|
GENESIS_DIFFICULTY* = 131072.Int256
|
||||||
GENESISGASLIMIT = 3141592
|
GENESIS_GAS_LIMIT* = 3141592.Int256
|
||||||
GENESISPARENTHASH = ZEROHASH32
|
GENESIS_PARENT_HASH* = ZERO_HASH32
|
||||||
GENESISCOINBASE = ZEROADDRESS
|
GENESIS_COINBASE* = ZERO_ADDRESS
|
||||||
GENESISNONCE = cstring"\\x00\\x00\\x00\\x00\\x00\\x00\\x00B"
|
GENESIS_NONCE* = cstring"\x00\x00\x00\x00\x00\x00\x00B"
|
||||||
GENESISMIXHASH = ZEROHASH32
|
GENESIS_MIX_HASH* = ZERO_HASH32
|
||||||
EMPTYSHA3 = cstring"\\xc5\\xd2F\\x01\\x86\\xf7#<\\x92~}\\xb2\\xdc\\xc7\\x03\\xc0\\xe5\\x00\\xb6S\\xca\\x82';{\\xfa\\xd8\\x04]\\x85\\xa4p"
|
GENESIS_EXTRA_DATA = cstring""
|
||||||
BLANKROOTHASH = cstring"V\\xe8\\x1f\\x17\\x1b\\xccU\\xa6\\xff\\x83E\\xe6\\x92\\xc0\\xf8n[H\\xe0\\x1b\\x99l\\xad\\xc0\\x01b/\\xb5\\xe3c\\xb4!"
|
EMPTYSHA3 = cstring"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p"
|
||||||
GASMODEXPQUADRATICDENOMINATOR = 20
|
BLANK_ROOT_HASH* = cstring"V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n[H\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!"
|
||||||
MAXPREVHEADERDEPTH = 256
|
GAS_MOD_EXP_QUADRATIC_DENOMINATOR* = 20
|
||||||
|
MAX_PREV_HEADER_DEPTH* = 256
|
||||||
|
151
src/db/chain.nim
Normal file
151
src/db/chain.nim
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
type
|
||||||
|
BaseChainDB* = ref object
|
||||||
|
# TODO db*: JournalDB
|
||||||
|
|
||||||
|
# proc makeBaseChainDB*(db: MemoryDB): BaseChainDB =
|
||||||
|
# result.db = JournalDB(db)
|
||||||
|
|
||||||
|
# proc exists*(self: BaseChainDB; key: cstring): bool =
|
||||||
|
# return self.db.exists(key)
|
||||||
|
|
||||||
|
# proc getCanonicalHead*(self: BaseChainDB): BlockHeader =
|
||||||
|
# if notself.exists(CANONICALHEADHASHDBKEY):
|
||||||
|
# raise newException(CanonicalHeadNotFound,
|
||||||
|
# "No canonical head set for this chain")
|
||||||
|
# return self.getBlockHeaderByHash(self.db.get(CANONICALHEADHASHDBKEY))
|
||||||
|
|
||||||
|
# proc getCanonicalBlockHeaderByNumber*(self: BaseChainDB; blockNumber: int): BlockHeader =
|
||||||
|
# ## Returns the block header with the given number in the canonical chain.
|
||||||
|
# ##
|
||||||
|
# ## Raises BlockNotFound if there's no block header with the given number in the
|
||||||
|
# ## canonical chain.
|
||||||
|
# validateUint256(blockNumber)
|
||||||
|
# return self.getBlockHeaderByHash(self.lookupBlockHash(blockNumber))
|
||||||
|
|
||||||
|
# proc getScore*(self: BaseChainDB; blockHash: cstring): int =
|
||||||
|
# return rlp.decode(self.db.get(makeBlockHashToScoreLookupKey(blockHash)))
|
||||||
|
|
||||||
|
# proc setAsCanonicalChainHead*(self: BaseChainDB; header: BlockHeader): void =
|
||||||
|
# ## Sets the header as the canonical chain HEAD.
|
||||||
|
# for h in reversed(self.findCommonAncestor(header)):
|
||||||
|
# self.addBlockNumberToHashLookup(h)
|
||||||
|
# try:
|
||||||
|
# self.getBlockHeaderByHash(header.hash)
|
||||||
|
# except BlockNotFound:
|
||||||
|
# raise newException(ValueError, "Cannot use unknown block hash as canonical head: {}".format(
|
||||||
|
# header.hash))
|
||||||
|
# self.db.set(CANONICALHEADHASHDBKEY, header.hash)
|
||||||
|
|
||||||
|
# iterator findCommonAncestor*(self: BaseChainDB; header: BlockHeader): BlockHeader =
|
||||||
|
# ## Returns the chain leading up from the given header until the first ancestor it has in
|
||||||
|
# ## common with our canonical chain.
|
||||||
|
# var h = header
|
||||||
|
# while true:
|
||||||
|
# yield h
|
||||||
|
# if h.parentHash == GENESISPARENTHASH:
|
||||||
|
# break
|
||||||
|
# try:
|
||||||
|
# var orig = self.getCanonicalBlockHeaderByNumber(h.blockNumber)
|
||||||
|
# except KeyError:
|
||||||
|
# nil
|
||||||
|
# h = self.getBlockHeaderByHash(h.parentHash)
|
||||||
|
|
||||||
|
# proc getBlockHeaderByHash*(self: BaseChainDB; blockHash: cstring): BlockHeader =
|
||||||
|
# ## Returns the requested block header as specified by block hash.
|
||||||
|
# ##
|
||||||
|
# ## Raises BlockNotFound if it is not present in the db.
|
||||||
|
# validateWord(blockHash)
|
||||||
|
# try:
|
||||||
|
# var block = self.db.get(blockHash)
|
||||||
|
# except KeyError:
|
||||||
|
# raise newException(BlockNotFound, "No block with hash {0} found".format(
|
||||||
|
# encodeHex(blockHash)))
|
||||||
|
# return rlp.decode(block)
|
||||||
|
|
||||||
|
# proc headerExists*(self: BaseChainDB; blockHash: cstring): bool =
|
||||||
|
# ## Returns True if the header with the given block hash is in our DB.
|
||||||
|
# return self.db.exists(blockHash)
|
||||||
|
|
||||||
|
# proc lookupBlockHash*(self: BaseChainDB; blockNumber: int): cstring =
|
||||||
|
# ## Return the block hash for the given block number.
|
||||||
|
# validateUint256(blockNumber)
|
||||||
|
# var
|
||||||
|
# numberToHashKey = makeBlockNumberToHashLookupKey(blockNumber)
|
||||||
|
# blockHash = rlp.decode(self.db.get(numberToHashKey))
|
||||||
|
# return blockHash
|
||||||
|
|
||||||
|
# iterator getReceipts*(self: BaseChainDB; header: BlockHeader; receiptClass: typedesc): Receipt =
|
||||||
|
# var receiptDb = HexaryTrie()
|
||||||
|
# for receiptIdx in itertools.count():
|
||||||
|
# var receiptKey = rlp.encode(receiptIdx)
|
||||||
|
# if receiptKey in receiptDb:
|
||||||
|
# var receiptData = receiptDb[receiptKey]
|
||||||
|
# yield rlp.decode(receiptData)
|
||||||
|
# else:
|
||||||
|
# break
|
||||||
|
|
||||||
|
# iterator getBlockTransactions*(self: BaseChainDB; blockHeader: BlockHeader;
|
||||||
|
# transactionClass: typedesc): FrontierTransaction =
|
||||||
|
# var transactionDb = HexaryTrie(self.db)
|
||||||
|
# for transactionIdx in itertools.count():
|
||||||
|
# var transactionKey = rlp.encode(transactionIdx)
|
||||||
|
# if transactionKey in transactionDb:
|
||||||
|
# var transactionData = transactionDb[transactionKey]
|
||||||
|
# yield rlp.decode(transactionData)
|
||||||
|
# else:
|
||||||
|
# break
|
||||||
|
|
||||||
|
# proc addBlockNumberToHashLookup*(self: BaseChainDB; header: BlockHeader): void =
|
||||||
|
# var blockNumberToHashKey = makeBlockNumberToHashLookupKey(header.blockNumber)
|
||||||
|
# self.db.set(blockNumberToHashKey, rlp.encode(header.hash))
|
||||||
|
|
||||||
|
# proc persistHeaderToDb*(self: BaseChainDB; header: BlockHeader): void =
|
||||||
|
# if header.parentHash != GENESISPARENTHASH and
|
||||||
|
# notself.headerExists(header.parentHash):
|
||||||
|
# raise newException(ParentNotFound, "Cannot persist block header ({}) with unknown parent ({})".format(
|
||||||
|
# encodeHex(header.hash), encodeHex(header.parentHash)))
|
||||||
|
# self.db.set(header.hash, rlp.encode(header))
|
||||||
|
# if header.parentHash == GENESISPARENTHASH:
|
||||||
|
# var score = header.difficulty
|
||||||
|
# else:
|
||||||
|
# score = self.getScore(header.parentHash) + header.difficulty
|
||||||
|
# self.db.set(makeBlockHashToScoreLookupKey(header.hash), rlp.encode(score))
|
||||||
|
# try:
|
||||||
|
# var headScore = self.getScore(self.getCanonicalHead().hash)
|
||||||
|
# except CanonicalHeadNotFound:
|
||||||
|
# self.setAsCanonicalChainHead(header)
|
||||||
|
|
||||||
|
# proc persistBlockToDb*(self: BaseChainDB; block: FrontierBlock): void =
|
||||||
|
# self.persistHeaderToDb(block.header)
|
||||||
|
# var transactionDb = HexaryTrie(self.db)
|
||||||
|
# for i in 0 ..< len(block.transactions):
|
||||||
|
# var indexKey = rlp.encode(i)
|
||||||
|
# transactionDb[indexKey] = rlp.encode(block.transactions[i])
|
||||||
|
# nil
|
||||||
|
# self.db.set(block.header.unclesHash, rlp.encode(block.uncles))
|
||||||
|
|
||||||
|
# proc addTransaction*(self: BaseChainDB; blockHeader: BlockHeader; indexKey: cstring;
|
||||||
|
# transaction: FrontierTransaction): cstring =
|
||||||
|
# var transactionDb = HexaryTrie(self.db)
|
||||||
|
# transactionDb[indexKey] = rlp.encode(transaction)
|
||||||
|
# return transactionDb.rootHash
|
||||||
|
|
||||||
|
# proc addReceipt*(self: BaseChainDB; blockHeader: BlockHeader; indexKey: cstring;
|
||||||
|
# receipt: Receipt): cstring =
|
||||||
|
# var receiptDb = HexaryTrie()
|
||||||
|
# receiptDb[indexKey] = rlp.encode(receipt)
|
||||||
|
# return receiptDb.rootHash
|
||||||
|
|
||||||
|
# proc snapshot*(self: BaseChainDB): UUID =
|
||||||
|
# return self.db.snapshot()
|
||||||
|
|
||||||
|
# proc commit*(self: BaseChainDB; checkpoint: UUID): void =
|
||||||
|
# self.db.commit(checkpoint)
|
||||||
|
|
||||||
|
# proc clear*(self: BaseChainDB): void =
|
||||||
|
# self.db.clear()
|
||||||
|
|
||||||
|
# proc getStateDb*(self: BaseChainDB; stateRoot: cstring; readOnly: bool): AccountStateDB =
|
||||||
|
# return AccountStateDB()
|
||||||
|
|
||||||
|
# var CANONICALHEADHASHDBKEY = cstring"v1:canonical_head_hash"
|
32
src/transaction.nim
Normal file
32
src/transaction.nim
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import
|
||||||
|
constants, errors
|
||||||
|
|
||||||
|
type
|
||||||
|
BaseTransaction* = ref object
|
||||||
|
nonce*: Int256
|
||||||
|
gasPrice*: Int256
|
||||||
|
gas*: Int256
|
||||||
|
to*: cstring
|
||||||
|
value*: Int256
|
||||||
|
data*: cstring
|
||||||
|
v*: Int256
|
||||||
|
r*: Int256
|
||||||
|
s*: Int256
|
||||||
|
|
||||||
|
proc intrinsicGas*(t: BaseTransaction): Int256 =
|
||||||
|
# Compute the baseline gas cost for this transaction. This is the amount
|
||||||
|
# of gas needed to send this transaction (but that is not actually used
|
||||||
|
# for computation)
|
||||||
|
raise newException(ValueError, "not implemented intrinsicGas")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
proc validate*(t: BaseTransaction) =
|
||||||
|
# Hook called during instantiation to ensure that all transaction
|
||||||
|
# parameters pass validation rules
|
||||||
|
if t.intrinsic_gas() > t.gas:
|
||||||
|
raise newException(ValidationError, "Insufficient gas")
|
||||||
|
# self.check_signature_validity()
|
37
src/utils/header.nim
Normal file
37
src/utils/header.nim
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
type
|
||||||
|
Header* = ref object
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
proc generateHeaderFromParentHeader*(
|
||||||
|
computeDifficultyFn: proc(parentHeader: Header, timestamp: int): int,
|
||||||
|
parentHeader: Header,
|
||||||
|
coinbase: cstring,
|
||||||
|
timestamp: int = -1,
|
||||||
|
extraData: cstring = cstring""): Header =
|
||||||
|
Header()
|
||||||
|
# Generate BlockHeader from state_root and parent_header
|
||||||
|
# if timestamp is None:
|
||||||
|
# timestamp = max(int(time.time()), parent_header.timestamp + 1)
|
||||||
|
# elif timestamp <= parent_header.timestamp:
|
||||||
|
# raise ValueError(
|
||||||
|
# "header.timestamp ({}) should be higher than"
|
||||||
|
# "parent_header.timestamp ({})".format(
|
||||||
|
# timestamp,
|
||||||
|
# parent_header.timestamp,
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# header = BlockHeader(
|
||||||
|
# difficulty=compute_difficulty_fn(parent_header, timestamp),
|
||||||
|
# block_number=(parent_header.block_number + 1),
|
||||||
|
# gas_limit=compute_gas_limit(
|
||||||
|
# parent_header,
|
||||||
|
# gas_limit_floor=GENESIS_GAS_LIMIT,
|
||||||
|
# ),
|
||||||
|
# timestamp=timestamp,
|
||||||
|
# parent_hash=parent_header.hash,
|
||||||
|
# state_root=parent_header.state_root,
|
||||||
|
# coinbase=coinbase,
|
||||||
|
# extra_data=extra_data,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# return header
|
61
src/vm/base.nim
Normal file
61
src/vm/base.nim
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import
|
||||||
|
../logging, ../constants, ../errors, ../transaction, ../computation, "../block", ../vm_state, ../db/chain, ../utils/db, ../utils/header
|
||||||
|
|
||||||
|
type
|
||||||
|
VM* = ref object of RootObj
|
||||||
|
# The VM class represents the Chain rules for a specific protocol definition
|
||||||
|
# such as the Frontier or Homestead network. Defining an Chain defining
|
||||||
|
# individual VM classes for each fork of the protocol rules within that
|
||||||
|
# network
|
||||||
|
|
||||||
|
chainDB*: BaseChainDB
|
||||||
|
isStateless*: bool
|
||||||
|
state*: BaseVMState
|
||||||
|
|
||||||
|
proc newVM*(header: Header, chainDB: BaseChainDB): VM =
|
||||||
|
new(result)
|
||||||
|
result.chainDB = chainDB
|
||||||
|
|
||||||
|
|
||||||
|
method addTransaction*(vm: var VM, transaction: BaseTransaction, computation: BaseComputation): Block =
|
||||||
|
# Add a transaction to the given block and save the block data into chaindb
|
||||||
|
var receipt = self.state.makeReceipt(transaction, computation)
|
||||||
|
var transactionIdx = len(vm.`block`.transactions)
|
||||||
|
return Block()
|
||||||
|
# var indexKey = rlp.encode(transaction_idx, sedes=rlp.sedes.big_endian_int)
|
||||||
|
|
||||||
|
# self.block.transactions.append(transaction)
|
||||||
|
|
||||||
|
# tx_root_hash = self.chaindb.add_transaction(self.block.header, index_key, transaction)
|
||||||
|
# receipt_root_hash = self.chaindb.add_receipt(self.block.header, index_key, receipt)
|
||||||
|
|
||||||
|
# self.block.bloom_filter |= receipt.bloom
|
||||||
|
|
||||||
|
# self.block.header.transaction_root = tx_root_hash
|
||||||
|
# self.block.header.receipt_root = receipt_root_hash
|
||||||
|
# self.block.header.bloom = int(self.block.bloom_filter)
|
||||||
|
# self.block.header.gas_used = receipt.gas_used
|
||||||
|
|
||||||
|
# return self.block
|
||||||
|
|
||||||
|
method applyTransaction*(vm: var VM, transaction: BaseTransaction): (BaseComputation, Block) =
|
||||||
|
# Apply the transaction to the vm in the current block
|
||||||
|
if vm.isStateless:
|
||||||
|
var (computation, b, trieData) = vm.state.applyTransaction(
|
||||||
|
vm.state,
|
||||||
|
transaction,
|
||||||
|
vm.`block`,
|
||||||
|
isStateless=true)
|
||||||
|
vm.`block` = b
|
||||||
|
result = (computation, b)
|
||||||
|
# Persist changed transaction and receipt key-values to self.chaindb.
|
||||||
|
else:
|
||||||
|
var (computation, _, _) = vm.state.applyTransaction(
|
||||||
|
vm.state,
|
||||||
|
transaction,
|
||||||
|
vm.`block`,
|
||||||
|
isStateless=false)
|
||||||
|
vm.addTransaction(transaction, computation)
|
||||||
|
|
||||||
|
result = (computation, vm.`block`)
|
||||||
|
|
@ -1,15 +1,15 @@
|
|||||||
import
|
import
|
||||||
strformat,
|
strformat, tables,
|
||||||
logging, constants, errors, utils/state
|
logging, constants, errors, transaction, db/chain, utils/state, utils/header
|
||||||
|
|
||||||
type
|
type
|
||||||
BaseVMState* = ref object of RootObj
|
BaseVMState* = ref object of RootObj
|
||||||
prevHeaders*: bool
|
prevHeaders*: seq[Header]
|
||||||
receipts*: bool
|
receipts*: seq[string]
|
||||||
computationClass*: bool
|
# computationClass*: bool
|
||||||
chaindb*: bool
|
chaindb*: BaseChainDB
|
||||||
accessLogs*: seq[bool]
|
accessLogs*: seq[string]
|
||||||
blockHeader*: bool
|
blockHeader*: Header
|
||||||
name*: string
|
name*: string
|
||||||
|
|
||||||
proc newBaseVMState*: BaseVMState =
|
proc newBaseVMState*: BaseVMState =
|
||||||
|
61
src/vm_state_transactions.nim
Normal file
61
src/vm_state_transactions.nim
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import
|
||||||
|
strformat, tables,
|
||||||
|
logging, constants, errors, computation, transaction, vm_state, "block", db/chain, utils/state, utils/header
|
||||||
|
|
||||||
|
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, Header) =
|
||||||
|
# Execute the transaction in the vm
|
||||||
|
raise newException(ValueError, "Must be implemented by subclasses")
|
||||||
|
|
||||||
|
|
||||||
|
method addTransaction*(vmState: var BaseVMState, transaction: BaseTransaction, computation: BaseComputation, b: Block): (Block, Table[cstring, cstring]) =
|
||||||
|
# Add a transaction to the given block and
|
||||||
|
# return `trieData` to store the transaction data in chaindb in VM layer
|
||||||
|
# Update the bloomFilter, transaction trie and receipt trie roots, bloom_filter,
|
||||||
|
# bloom, and usedGas of the block
|
||||||
|
# transaction: the executed transaction
|
||||||
|
# computation: the Computation object with executed result
|
||||||
|
# block: the Block which the transaction is added in
|
||||||
|
# var receipt = vmState.makeReceipt(transaction, computation)
|
||||||
|
# vmState.add_receipt(receipt)
|
||||||
|
|
||||||
|
# block.transactions.append(transaction)
|
||||||
|
|
||||||
|
# # Get trie roots and changed key-values.
|
||||||
|
# tx_root_hash, tx_kv_nodes = make_trie_root_and_nodes(block.transactions)
|
||||||
|
# receipt_root_hash, receipt_kv_nodes = make_trie_root_and_nodes(self.receipts)
|
||||||
|
|
||||||
|
# trie_data = merge(tx_kv_nodes, receipt_kv_nodes)
|
||||||
|
|
||||||
|
# block.bloom_filter |= receipt.bloom
|
||||||
|
|
||||||
|
# block.header.transaction_root = tx_root_hash
|
||||||
|
# block.header.receipt_root = receipt_root_hash
|
||||||
|
# block.header.bloom = int(block.bloom_filter)
|
||||||
|
# block.header.gas_used = receipt.gas_used
|
||||||
|
|
||||||
|
# return block, trie_data
|
||||||
|
result = (b, initTable[cstring, cstring]())
|
||||||
|
|
||||||
|
method applyTransaction*(
|
||||||
|
vmState: var BaseVMState,
|
||||||
|
transaction: BaseTransaction,
|
||||||
|
b: Block,
|
||||||
|
isStateless: bool): (BaseComputation, Block, Table[cstring, cstring]) =
|
||||||
|
# Apply transaction to the given block
|
||||||
|
# transaction: the transaction need to be applied
|
||||||
|
# b: the block which the transaction applies on
|
||||||
|
# isStateless: if isStateless, call vmState.addTransaction to set block
|
||||||
|
|
||||||
|
if isStateless:
|
||||||
|
var ourBlock = b # deepcopy
|
||||||
|
vmState.blockHeader = b.header
|
||||||
|
var (computation, blockHeader) = vmState.executeTransaction(transaction)
|
||||||
|
|
||||||
|
ourBlock.header = blockHeader
|
||||||
|
var trieData: Table[cstring, cstring]
|
||||||
|
(ourBlock, trieData) = vmState.addTransaction(transaction, computation, ourBlock)
|
||||||
|
|
||||||
|
result = (computation, ourBlock, trieData)
|
||||||
|
else:
|
||||||
|
var (computation, blockHeader) = vmState.executeTransaction(transaction)
|
||||||
|
return (computation, nil, initTable[cstring, cstring]())
|
Loading…
x
Reference in New Issue
Block a user