Few steps forward vm_tests (#15)
* Enable vm_tests, remove usage of from keyword as a variable name * Fix Genesis types and use the new EthTime * Add a new VMKind enum (py-evm vmclass runtime type) * renaming block_obj to block_types * chain.BlockHeader and utils.header.Header are the same thing (BlockHeader in py-evm) * For now blockNumbers are UInt256 * EoD merge: vm_test compiles and does not throw computation error * running full transactions is too early
This commit is contained in:
parent
8cf8811310
commit
6654576c6a
|
@ -6,13 +6,15 @@
|
|||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
logging, constants, utils / header, ttmath
|
||||
ttmath,
|
||||
./logging, ./constants,
|
||||
./utils/header
|
||||
|
||||
type
|
||||
CountableList*[T] = ref object
|
||||
elements: seq[T] # TODO
|
||||
|
||||
Block* = ref object of RootObj
|
||||
header*: Header
|
||||
uncles*: CountableList[Header]
|
||||
header*: BlockHeader
|
||||
uncles*: CountableList[BlockHeader]
|
||||
blockNumber*: UInt256
|
|
@ -7,12 +7,10 @@
|
|||
|
||||
import
|
||||
tables, ttmath,
|
||||
logging, constants, errors, validation, utils / hexadecimal, vm / base, db / db_chain
|
||||
./logging, ./constants, ./errors, ./validation, ./utils/hexadecimal, ./vm/base, ./db/db_chain,
|
||||
./utils/header, ./vm/forks/frontier/vm
|
||||
|
||||
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
|
||||
|
@ -21,7 +19,7 @@ type
|
|||
header*: BlockHeader
|
||||
logger*: Logger
|
||||
networkId*: string
|
||||
vmsByRange*: seq[tuple[blockNumber: Int256, vm: VM]] # TODO
|
||||
vmsByRange*: seq[tuple[blockNumber: UInt256, vmk: VMkind]] # TODO: VM should actually be a runtime typedesc(VM)
|
||||
importBlock*: bool
|
||||
validateBlock*: bool
|
||||
db*: BaseChainDB
|
||||
|
@ -30,9 +28,9 @@ type
|
|||
fundedAddressPrivateKey*: string
|
||||
|
||||
GenesisParams* = ref object
|
||||
blockNumber*: Int256
|
||||
difficulty*: Int256
|
||||
gasLimit*: Int256
|
||||
blockNumber*: UInt256
|
||||
difficulty*: UInt256
|
||||
gasLimit*: UInt256
|
||||
parentHash*: string
|
||||
coinbase*: string
|
||||
nonce*: string
|
||||
|
@ -47,9 +45,9 @@ type
|
|||
code*: string
|
||||
|
||||
|
||||
proc configureChain*(name: string, blockNumber: Int256, vm: VM, importBlock: bool = true, validateBlock: bool = true): Chain =
|
||||
proc configureChain*(name: string, blockNumber: UInt256, vmk: VMKind, importBlock: bool = true, validateBlock: bool = true): Chain =
|
||||
new(result)
|
||||
result.vmsByRange = @[(blockNumber: blockNumber, vm: vm)]
|
||||
result.vmsByRange = @[(blockNumber: blockNumber, vmk: vmk)]
|
||||
result.importBlock = importBlock
|
||||
result.validateBlock = validateBlock
|
||||
|
||||
|
@ -75,3 +73,29 @@ proc fromGenesis*(
|
|||
result.vmsByRange = chain.vmsByRange
|
||||
# TODO
|
||||
# chainDB.persistBlockToDB(result.getBlock)
|
||||
|
||||
proc getVMClassForBlockNumber*(chain: Chain, blockNumber: UInt256): VMKind =
|
||||
## Returns the VM class for the given block number
|
||||
# TODO should the return value be a typedesc?
|
||||
|
||||
# TODO: validate_block_number
|
||||
for idx in countdown(chain.vmsByRange.high, chain.vmsByRange.low):
|
||||
let (n, vmk) = chain.vmsByRange[idx]
|
||||
if blockNumber >= n:
|
||||
return vmk
|
||||
|
||||
raise newException(ValueError, "VM not found for block #" & $blockNumber) # TODO: VMNotFound exception
|
||||
|
||||
proc getVM*(chain: Chain, header: BlockHeader = nil): VM =
|
||||
## Returns the VM instance for the given block number
|
||||
|
||||
# shadowing input param
|
||||
let header = if header.isNil: chain.header
|
||||
else: header
|
||||
|
||||
let vm_class = chain.getVMClassForBlockNumber(header.blockNumber)
|
||||
|
||||
case vm_class:
|
||||
of vmkFrontier: result = newFrontierVM(header, chain.db)
|
||||
else:
|
||||
raise newException(ValueError, "Chain: only FrontierVM is implemented")
|
||||
|
|
|
@ -33,7 +33,7 @@ var c = BaseComputation(
|
|||
vmState: BaseVMState(
|
||||
prevHeaders: @[],
|
||||
chaindb: BaseChainDB(),
|
||||
blockHeader: Header(),
|
||||
blockHeader: BlockHeader(),
|
||||
name: "zero"),
|
||||
msg: msg,
|
||||
memory: mem,
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
import ../constants, ttmath, strformat, times, ../validation
|
||||
|
||||
type
|
||||
Header* = ref object
|
||||
BlockHeader* = ref object
|
||||
# Note: this is defined in evm/rlp/headers in the original repo
|
||||
timestamp*: EthTime
|
||||
difficulty*: UInt256
|
||||
blockNumber*: UInt256
|
||||
|
@ -17,27 +18,26 @@ type
|
|||
unclesHash*: string
|
||||
coinbase*: string
|
||||
stateRoot*: string
|
||||
# TODO: incomplete
|
||||
|
||||
# TODO
|
||||
proc hasUncles*(header: BlockHeader): bool = header.uncles_hash != EMPTY_UNCLE_HASH
|
||||
|
||||
proc hasUncles*(header: Header): bool = header.uncles_hash != EMPTY_UNCLE_HASH
|
||||
|
||||
proc gasUsed*(header: Header): UInt256 =
|
||||
proc gasUsed*(header: BlockHeader): UInt256 =
|
||||
# TODO
|
||||
# Should this be calculated/a proc? Parity and Py-Evm just have it as a field.
|
||||
0.u256
|
||||
|
||||
proc gasLimit*(header: Header): UInt256 =
|
||||
proc gasLimit*(header: BlockHeader): UInt256 =
|
||||
# TODO
|
||||
0.u256
|
||||
|
||||
proc `$`*(header: Header): string =
|
||||
proc `$`*(header: BlockHeader): string =
|
||||
if header.isNil:
|
||||
result = "nil"
|
||||
else:
|
||||
result = &"Header(timestamp: {header.timestamp} difficulty: {header.difficulty} blockNumber: {header.blockNumber} gasLimit: {header.gasLimit})"
|
||||
result = &"BlockHeader(timestamp: {header.timestamp} difficulty: {header.difficulty} blockNumber: {header.blockNumber} gasLimit: {header.gasLimit})"
|
||||
|
||||
proc gasLimitBounds*(parent: Header): (UInt256, UInt256) =
|
||||
proc gasLimitBounds*(parent: BlockHeader): (UInt256, UInt256) =
|
||||
## Compute the boundaries for the block gas limit based on the parent block.
|
||||
let
|
||||
boundary_range = parent.gasLimit div GAS_LIMIT_ADJUSTMENT_FACTOR
|
||||
|
@ -46,7 +46,7 @@ proc gasLimitBounds*(parent: Header): (UInt256, UInt256) =
|
|||
return (lower_bound, upper_bound)
|
||||
|
||||
#[
|
||||
proc validate_gaslimit(header: Header):
|
||||
proc validate_gaslimit(header: BlockHeader):
|
||||
let parent_header = getBlockHeaderByHash(header.parent_hash)
|
||||
low_bound, high_bound = compute_gas_limit_bounds(parent_header)
|
||||
if header.gas_limit < low_bound:
|
||||
|
@ -59,7 +59,7 @@ proc validate_gaslimit(header: Header):
|
|||
encode_hex(header.hash), header.gas_limit, high_bound))
|
||||
]#
|
||||
|
||||
proc computeGasLimit*(parent: Header, gasLimitFloor: UInt256): UInt256 =
|
||||
proc computeGasLimit*(parent: BlockHeader, gasLimitFloor: UInt256): UInt256 =
|
||||
#[
|
||||
For each block:
|
||||
- decrease by 1/1024th of the gas limit from the previous block
|
||||
|
@ -98,13 +98,13 @@ proc computeGasLimit*(parent: Header, gasLimitFloor: UInt256): UInt256 =
|
|||
return gas_limit
|
||||
|
||||
proc generateHeaderFromParentHeader*(
|
||||
computeDifficultyFn: proc(parentHeader: Header, timestamp: int): int,
|
||||
parent: Header,
|
||||
computeDifficultyFn: proc(parentHeader: BlockHeader, timestamp: int): int,
|
||||
parent: BlockHeader,
|
||||
coinbase: string,
|
||||
timestamp: int = -1,
|
||||
extraData: string = ""): Header =
|
||||
extraData: string = ""): BlockHeader =
|
||||
# TODO: validateGt(timestamp, parent.timestamp)
|
||||
result = Header(
|
||||
result = BlockHeader(
|
||||
timestamp: max(getTime(), parent.timestamp + 1.milliseconds), # Note: Py-evm uses +1 second, not ms
|
||||
block_number: (parent.block_number + u256(1)),
|
||||
# TODO: difficulty: parent.computeDifficulty(parent.timestamp),
|
||||
|
|
|
@ -6,9 +6,14 @@
|
|||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
../logging, ../constants, ../errors, ../transaction, ../types, ../computation, ../block_obj, ../vm_state, ../vm_state_transactions, ../db/db_chain, ../utils/header
|
||||
../logging, ../constants, ../errors, ../transaction, ../types, ../computation, ../block_types, ../vm_state, ../vm_state_transactions, ../db/db_chain, ../utils/header
|
||||
|
||||
type
|
||||
VMkind* = enum
|
||||
## List of VMs forks (py-evm vm_class) of the Ethereum network
|
||||
# TODO: used in Chain.vmsByRange: can we store the runtimetime in a seq/tuple instead?
|
||||
vmkFrontier, vmkHomestead, vmkTangerineWhistle, vmkSpuriousDragon, vmkByzantium
|
||||
|
||||
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
|
||||
|
@ -20,7 +25,7 @@ type
|
|||
state*: BaseVMState
|
||||
`block`*: Block
|
||||
|
||||
proc newVM*(header: Header, chainDB: BaseChainDB): VM =
|
||||
proc newVM*(header: BlockHeader, chainDB: BaseChainDB): VM =
|
||||
new(result)
|
||||
result.chainDB = chainDB
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
import
|
||||
../../../logging, ../../../constants, ../../../errors, ../../../transaction,
|
||||
../../../block_obj,
|
||||
../../../block_types,
|
||||
../../../utils/header
|
||||
|
||||
type
|
||||
FrontierBlock* = object of Block
|
||||
FrontierBlock* = ref object of Block
|
||||
# bloomFilter*: BloomFilter
|
||||
# header*: BlockHeader
|
||||
transactions*: seq[BaseTransaction]
|
||||
|
@ -25,13 +25,13 @@ type
|
|||
# rlp, rlp.sedes, eth_bloom, evm.constants, evm.rlp.receipts, evm.rlp.blocks,
|
||||
# evm.rlp.headers, evm.utils.keccak, transactions
|
||||
|
||||
# method makeFrontierBlock*(header: auto; transactions: auto; uncles: void): auto =
|
||||
# if transactions is None:
|
||||
# transactions = @[]
|
||||
# if uncles is None:
|
||||
# uncles = @[]
|
||||
# result.bloomFilter = BloomFilter(header.bloom)
|
||||
# super(FrontierBlock, result).__init__()
|
||||
proc makeFrontierBlock*(header: BlockHeader; transactions: seq[BaseTransaction]; uncles: void): FrontierBlock =
|
||||
new result
|
||||
if transactions.len == 0:
|
||||
result.transactions = @[]
|
||||
# if uncles is None:
|
||||
# uncles = @[]
|
||||
# result.bloomFilter = BloomFilter(header.bloom)
|
||||
|
||||
# method number*(self: FrontierBlock): int =
|
||||
# return self.header.blockNumber
|
||||
|
|
|
@ -8,21 +8,21 @@
|
|||
import
|
||||
logging, constants, errors, validation, utils/header, vm / forks / frontier / vm
|
||||
|
||||
method computeDifficulty*(parentHeader: Header, timestamp: int): Int256 =
|
||||
validateGt(timestamp, parentHeader.timestamp, title="Header timestamp")
|
||||
method computeDifficulty*(parentHeader: BlockHeader, timestamp: int): Int256 =
|
||||
validateGt(timestamp, parentHeader.timestamp, title="BlockHeader timestamp")
|
||||
let offset = parentHeader.difficulty div DIFFICULTY_ADJUSTMENT_DENOMINATOR
|
||||
# We set the minimum to the lowest of the protocol minimum and the parent
|
||||
# minimum to allow for the initial frontier *warming* period during which
|
||||
# the difficulty begins lower than the protocol minimum
|
||||
let difficultyMinimum = min(parentHeader.difficulty, DIFFICULTY_MINIMUM)
|
||||
# let test = (timestamp - parentHeader.timestamp).Int256 < FRONTIER_DIFFICULTY_ADJUSTMENT_CUTOFF
|
||||
# let baseDifficulty = max(parent.Header.difficulty + (if test: offset else: -offset), difficultyMinimum)
|
||||
# let baseDifficulty = max(parent.BlockHeader.difficulty + (if test: offset else: -offset), difficultyMinimum)
|
||||
# # Adjust for difficulty bomb
|
||||
# let numBombPeriods = ((parentHeader.blockNumber + 1) div BOMB_EXPONENTIAL_PERIOD) - BOMB_EXPONENTIAL_FREE_PERIODS
|
||||
# result = if numBombPeriods >= 0: max(baseDifficulty + 2.Int256 ^ numBombPeriods, DIFFICULTY_MINIMUM) else: baseDifficulty
|
||||
result = 0.Int256
|
||||
|
||||
method createHeaderFromParent*(parentHeader: Header): Header =
|
||||
method createHeaderFromParent*(parentHeader: BlockHeader): BlockHeader =
|
||||
# TODO
|
||||
result = Header()
|
||||
result = BlockHeader()
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ proc newFrontierVMState*: FrontierVMState =
|
|||
result.prevHeaders = @[]
|
||||
result.name = "FrontierVM"
|
||||
result.accessLogs = newAccessLogs()
|
||||
result.blockHeader = Header(hash: "TODO", coinbase: "TODO", stateRoot: "TODO")
|
||||
result.blockHeader = BlockHeader(hash: "TODO", coinbase: "TODO", stateRoot: "TODO")
|
||||
|
||||
# import
|
||||
# py2nim_helpers, __future__, rlp, evm, evm.constants, evm.exceptions, evm.rlp.logs,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import
|
||||
../../../logging, ../../../constants, ../../../errors,
|
||||
ttmath,
|
||||
../../../block_obj,
|
||||
../../../block_types,
|
||||
../../../vm/[base, stack], ../../../db/db_chain, ../../../utils/header,
|
||||
./frontier_block, ./frontier_vm_state, ./frontier_validation
|
||||
|
||||
|
@ -29,8 +29,9 @@ method getUncleReward(vm: FrontierVM, blockNumber: UInt256, uncle: Block): UInt2
|
|||
method getNephewReward(vm: FrontierVM): UInt256 =
|
||||
vm.getBlockReward() div 32
|
||||
|
||||
proc newFrontierVM*(header: Header, chainDB: BaseChainDB): FrontierVM =
|
||||
proc newFrontierVM*(header: BlockHeader, chainDB: BaseChainDB): FrontierVM =
|
||||
new(result)
|
||||
result.chainDB = chainDB
|
||||
result.isStateless = true
|
||||
result.state = newFrontierVMState()
|
||||
result.`block` = makeFrontierBlock(header, @[])
|
||||
|
|
|
@ -7,15 +7,16 @@
|
|||
|
||||
import
|
||||
macros, strformat, tables,
|
||||
logging, constants, ttmath, errors, transaction, db/db_chain, utils/state, utils/header
|
||||
ttmath,
|
||||
./logging, ./constants, ./errors, ./transaction, ./db/[db_chain, state_db], ./utils/state, ./utils/header
|
||||
|
||||
type
|
||||
BaseVMState* = ref object of RootObj
|
||||
prevHeaders*: seq[Header]
|
||||
prevHeaders*: seq[BlockHeader]
|
||||
# receipts*:
|
||||
chaindb*: BaseChainDB
|
||||
accessLogs*: AccessLogs
|
||||
blockHeader*: Header
|
||||
blockHeader*: BlockHeader
|
||||
name*: string
|
||||
|
||||
AccessLogs* = ref object
|
||||
|
@ -40,7 +41,7 @@ proc newBaseVMState*: BaseVMState =
|
|||
result.prevHeaders = @[]
|
||||
result.name = "BaseVM"
|
||||
result.accessLogs = newAccessLogs()
|
||||
result.blockHeader = Header(hash: "TODO", coinbase: "TODO", stateRoot: "TODO")
|
||||
result.blockHeader = BlockHeader(hash: "TODO", coinbase: "TODO", stateRoot: "TODO")
|
||||
|
||||
method logger*(vmState: BaseVMState): Logger =
|
||||
logging.getLogger(&"evm.vmState.{vmState.name}")
|
||||
|
@ -97,3 +98,6 @@ macro db*(vmState: untyped, readOnly: untyped, handler: untyped): untyped =
|
|||
# leaving the context.
|
||||
# TODO `db`.db = nil
|
||||
# state._trie = None
|
||||
|
||||
proc readOnlyStateDB*(vmState: BaseVMState): AccountStateDB {.inline.}=
|
||||
vmState.chaindb.getStateDb("", readOnly = true)
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
|
||||
import
|
||||
strformat, tables,
|
||||
logging, constants, errors, computation, transaction, types, vm_state, block_obj, db / db_chain, utils / [state, header]
|
||||
logging, constants, errors, computation, transaction, types, vm_state, block_types, db / db_chain, utils / [state, header]
|
||||
|
||||
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, Header) =
|
||||
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, BlockHeader) {.base.}=
|
||||
# Execute the transaction in the vm
|
||||
# TODO: introduced here: https://github.com/ethereum/py-evm/commit/21c57f2d56ab91bb62723c3f9ebe291d0b132dde
|
||||
# Refactored/Removed here: https://github.com/ethereum/py-evm/commit/cc991bf
|
||||
# Deleted here: https://github.com/ethereum/py-evm/commit/746defb6f8e83cee2c352a0ab8690e1281c4227c
|
||||
raise newException(ValueError, "Must be implemented by subclasses")
|
||||
|
||||
|
||||
|
|
|
@ -10,5 +10,6 @@ import ./test_code_stream,
|
|||
./test_memory,
|
||||
./test_stack,
|
||||
./test_opcode
|
||||
# ./test_vm
|
||||
|
||||
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
# * 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 unittest, strformat, tables, constants, chain, ttmath, vm / forks / frontier / vm, utils / [header, address], db / db_chain, db / backends / memory_backend
|
||||
import
|
||||
unittest, strformat, tables, times,
|
||||
ttmath,
|
||||
../src/[constants, chain, vm/base, vm/forks/frontier/vm, utils/header, utils/address, db/db_chain, db/backends/memory_backend]
|
||||
|
||||
proc chainWithoutBlockValidation: Chain =
|
||||
result = configureChain("TestChain", GENESIS_BLOCK_NUMBER, newFrontierVM(Header(), newBaseChainDB(newMemoryDB())), false, false)
|
||||
proc chainWithoutBlockValidation*: Chain =
|
||||
result = configureChain("TestChain", GENESIS_BLOCK_NUMBER, vmkFrontier, false, false)
|
||||
let privateKey = "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" # TODO privateKey(decodeHex("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"))
|
||||
let fundedAddr = privateKey # privateKey.publicKey.toCanonicalAddress
|
||||
let initialBalance = 100_000_000
|
||||
|
@ -21,7 +24,7 @@ proc chainWithoutBlockValidation: Chain =
|
|||
nonce: GENESIS_NONCE,
|
||||
mixHash: GENESIS_MIX_HASH,
|
||||
extraData: GENESIS_EXTRA_DATA,
|
||||
timestamp: 1501851927,
|
||||
timestamp: fromUnix 1501851927,
|
||||
stateRoot: "0x9d354f9b5ba851a35eced279ef377111387197581429cfcc7f744ef89a30b5d4") #.decodeHex)
|
||||
let genesisState = {"fundedAddr": FundedAddress(balance: initialBalance.int256, nonce: 0, code: "")}.toTable()
|
||||
result = fromGenesis(
|
||||
|
|
|
@ -10,7 +10,8 @@ import
|
|||
ttmath,
|
||||
../src/utils/[hexadecimal, address, padding],
|
||||
../src/[chain, vm_state, constants],
|
||||
../src/db/[db_chain, state_db], ../src/vm/forks/frontier/vm
|
||||
../src/db/[db_chain, state_db], ../src/vm/forks/frontier/vm,
|
||||
../src/vm/base, ../src/transaction
|
||||
|
||||
type
|
||||
Status* {.pure.} = enum OK, Fail, Skip
|
||||
|
@ -91,3 +92,21 @@ proc setupStateDB*(desiredState: JsonNode, stateDB: var AccountStateDB) =
|
|||
|
||||
proc getHexadecimalInt*(j: JsonNode): int =
|
||||
discard parseHex(j.getStr, result)
|
||||
|
||||
method newTransaction*(
|
||||
vm: VM, addr_from, addr_to: string,
|
||||
amount: UInt256,
|
||||
private_key: string,
|
||||
gas_price = 10.u256,
|
||||
gas = 100000.u256,
|
||||
data: seq[byte] = @[]
|
||||
): BaseTransaction =
|
||||
# TODO: amount should be an Int to deal with negatives
|
||||
new result
|
||||
|
||||
# Todo getStateDB is incomplete
|
||||
let nonce = vm.state.readOnlyStateDB.getNonce(addr_from)
|
||||
|
||||
# TODO
|
||||
# if !private key: create_unsigned_transaction
|
||||
# else: create_signed_transaction
|
||||
|
|
|
@ -17,8 +17,8 @@ import
|
|||
|
||||
|
||||
proc testCode(code: string, gas: UInt256): BaseComputation =
|
||||
var vm = newFrontierVM(Header(), newBaseChainDB(newMemoryDB()))
|
||||
let header = Header()
|
||||
var vm = newFrontierVM(BlockHeader(), newBaseChainDB(newMemoryDB()))
|
||||
let header = BlockHeader()
|
||||
# coinbase: "",
|
||||
# difficulty: fixture{"env"}{"currentDifficulty"}.getHexadecimalInt.u256,
|
||||
# blockNumber: fixture{"env"}{"currentNumber"}.getHexadecimalInt.u256,
|
||||
|
|
|
@ -6,30 +6,39 @@
|
|||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
unittest,
|
||||
test_helpers, .. / src / [db / backends / memory, db / chain, constants, utils / hexadecimal]
|
||||
unittest, ttmath,
|
||||
./test_helpers, ./fixtures,
|
||||
../src/[db/backends/memory_backend, db/state_db, chain, constants, utils/hexadecimal, vm_state],
|
||||
../src/[vm/base, computation]
|
||||
|
||||
suite "vm":
|
||||
test "apply no validation":
|
||||
import typetraits
|
||||
|
||||
suite "VM":
|
||||
test "Apply transaction with no validation":
|
||||
var
|
||||
chain = testChain()
|
||||
chain = chainWithoutBlockValidation()
|
||||
vm = chain.getVM()
|
||||
txIdx = len(vm.`block`.transactions)
|
||||
# txIdx = len(vm.`block`.transactions) # Can't take len of a runtime field
|
||||
let
|
||||
recipient = decodeHex("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c")
|
||||
amount = 100.Int256
|
||||
amount = 100.u256
|
||||
ethaddr_from = chain.fundedAddress
|
||||
tx = newTransaction(vm, ethaddr_from, recipient, amount, chain.fundedAddressPrivateKey)
|
||||
# (computation, _) = vm.applyTransaction(tx)
|
||||
# accessLogs = computation.vmState.accessLogs
|
||||
|
||||
var from = chain.fundedAddress
|
||||
var tx = newTransaction(vm, from, recipient, amount, chain.fundedAddressPrivateKey)
|
||||
var (computation, _) = vm.applyTransaction(tx)
|
||||
var accessLogs = computation.vmState.accessLogs
|
||||
# check(not computation.isError)
|
||||
|
||||
check(not computation.isError)
|
||||
let
|
||||
txGas = tx.gasPrice * constants.GAS_TX
|
||||
state_db = vm.state.readOnlyStateDB
|
||||
b = vm.`block`
|
||||
|
||||
var txGas = tx.gasPrice * constants.GAS_TX
|
||||
inDb(vm.state.stateDb(readOnly=true)):
|
||||
check(db.getBalance(from) == chain.fundedAddressInitialBalance - amount - txGas)
|
||||
check(db.getBalance(recipient) == amount)
|
||||
var b = vm.`block`
|
||||
check(b.transactions[txIdx] == tx)
|
||||
check(b.header.gasUsed == constants.GAS_TX)
|
||||
echo state_db.getBalance(ethaddr_from).type.name
|
||||
|
||||
# check:
|
||||
# state_db.getBalance(ethaddr_from) == chain.fundedAddressInitialBalance - amount - txGas # TODO: this really should be i256
|
||||
# state_db.getBalance(recipient) == amount
|
||||
# b.transactions[txIdx] == tx
|
||||
# b.header.gasUsed == constants.GAS_TX
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
|||
for label, child in fixtures:
|
||||
fixture = child
|
||||
break
|
||||
var vm = newFrontierVM(Header(), newBaseChainDB(newMemoryDB()))
|
||||
let header = Header(
|
||||
var vm = newFrontierVM(BlockHeader(), newBaseChainDB(newMemoryDB()))
|
||||
let header = BlockHeader(
|
||||
coinbase: fixture{"env"}{"currentCoinbase"}.getStr,
|
||||
difficulty: fixture{"env"}{"currentDifficulty"}.getHexadecimalInt.u256,
|
||||
blockNumber: fixture{"env"}{"currentNumber"}.getHexadecimalInt.u256,
|
||||
|
|
Loading…
Reference in New Issue