Reorganize VM/interpreter + cleanup (#52)
* Move and cleanup interpreter files - prepare for redesign of VM * fix call comment aobut recursive dependencies * memory: use a template again and avoid (?) a cstring-> string conversion * Fix stack test regression * Fix recursive dependency on logging_ops, test_vm_json compiles but regression :/ * Fix signextend regression * Fix 3 signed test and sha3 test
This commit is contained in:
parent
05275f9773
commit
c26c751f9b
106
nimbus/chain.nim
106
nimbus/chain.nim
|
@ -1,106 +0,0 @@
|
||||||
# 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
|
|
||||||
tables, stint, eth_common, eth_keys,
|
|
||||||
./logging, ./constants, ./errors, ./validation, ./utils/hexadecimal, ./vm/base, ./db/db_chain,
|
|
||||||
./utils/header, ./vm/forks/f20150730_frontier/frontier_vm
|
|
||||||
|
|
||||||
type
|
|
||||||
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*: string
|
|
||||||
vmsByRange*: seq[tuple[blockNumber: UInt256, vmk: VMkind]] # TODO: VM should actually be a runtime typedesc(VM)
|
|
||||||
importBlock*: bool
|
|
||||||
validateBlock*: bool
|
|
||||||
db*: BaseChainDB
|
|
||||||
fundedAddress*: EthAddress
|
|
||||||
fundedAddressInitialBalance*: int
|
|
||||||
fundedAddressPrivateKey*: PrivateKey
|
|
||||||
|
|
||||||
GenesisParams* = ref object
|
|
||||||
blockNumber*: BlockNumber
|
|
||||||
difficulty*: UInt256
|
|
||||||
gasLimit*: GasInt
|
|
||||||
parentHash*: Hash256
|
|
||||||
coinbase*: EthAddress
|
|
||||||
nonce*: string
|
|
||||||
mixHash*: Hash256
|
|
||||||
extraData*: string
|
|
||||||
timestamp*: EthTime
|
|
||||||
stateRoot*: Hash256
|
|
||||||
|
|
||||||
FundedAddress* = ref object
|
|
||||||
balance*: Int256
|
|
||||||
nonce*: int
|
|
||||||
code*: string
|
|
||||||
|
|
||||||
|
|
||||||
proc configureChain*(name: string, blockNumber: UInt256, vmk: VMKind, importBlock: bool = true, validateBlock: bool = true): Chain =
|
|
||||||
new(result)
|
|
||||||
result.vmsByRange = @[(blockNumber: blockNumber, vmk: vmk)]
|
|
||||||
result.importBlock = importBlock
|
|
||||||
result.validateBlock = validateBlock
|
|
||||||
|
|
||||||
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)
|
|
||||||
# TODO
|
|
||||||
# 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")
|
|
||||||
result.importBlock = chain.importBlock
|
|
||||||
result.validateBlock = chain.validateBlock
|
|
||||||
result.vmsByRange = chain.vmsByRange
|
|
||||||
# TODO
|
|
||||||
# chainDB.persistBlockToDB(result.getBlock)
|
|
||||||
|
|
||||||
|
|
||||||
proc getVMClassForBlockNumber*(chain: Chain, blockNumber: BlockNumber): VMKind =
|
|
||||||
## Returns the VM class for the given block number
|
|
||||||
# TODO - Refactoring: superseded by newNimbusVM for the time being #https://github.com/status-im/nimbus/pull/37
|
|
||||||
# TODO - Refactoring: redundant with constants.nim `toFork`
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# TODO - Refactoring: superseded by newNimbusVM for the time being #https://github.com/status-im/nimbus/pull/37
|
|
||||||
|
|
||||||
proc getVM*(chain: Chain, header: BlockHeader): VM =
|
|
||||||
## Returns the VM instance for the given block number
|
|
||||||
# TODO - Refactoring: superseded by newNimbusVM for the time being #https://github.com/status-im/nimbus/pull/37
|
|
||||||
# TODO - Refactoring: redundant with constants.nim `toFork`
|
|
||||||
# shadowing input param
|
|
||||||
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")
|
|
||||||
|
|
||||||
proc getVM*(chain: Chain): VM {.inline.} = getVM(chain, chain.header)
|
|
|
@ -2,103 +2,6 @@
|
||||||
import
|
import
|
||||||
stint, math, strutils, utils/padding, eth_common
|
stint, math, strutils, utils/padding, eth_common
|
||||||
|
|
||||||
proc int256*(i: int): Int256 =
|
|
||||||
i.i256
|
|
||||||
|
|
||||||
# template i256*(i: int): Int256 =
|
|
||||||
# i.initBigInt
|
|
||||||
|
|
||||||
template i256*(i: Int256): Int256 =
|
|
||||||
i
|
|
||||||
|
|
||||||
template u256*(i: int): UInt256 =
|
|
||||||
i.uint.u256
|
|
||||||
|
|
||||||
template u256*(i: UInt256): UInt256 =
|
|
||||||
i
|
|
||||||
|
|
||||||
template getInt*(i: int): int =
|
|
||||||
i
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# We'll have a fast fixed i256, for now this works
|
|
||||||
|
|
||||||
proc `==`*(a: Int256, b: int): bool =
|
|
||||||
a == b.i256
|
|
||||||
|
|
||||||
proc `!=`*(a: Int256, b: int): bool =
|
|
||||||
a != b.i256
|
|
||||||
|
|
||||||
proc `==`*(a: UInt256, b: int): bool =
|
|
||||||
a == b.u256
|
|
||||||
|
|
||||||
proc `!=`*(a: UInt256, b: int): bool =
|
|
||||||
a != b.u256
|
|
||||||
|
|
||||||
# proc `^`*(base: int; exp: int): UInt256 =
|
|
||||||
# let base = base.u256
|
|
||||||
# var ex = exp
|
|
||||||
# result = 1.u256
|
|
||||||
# while ex > 0:
|
|
||||||
# result = result * base
|
|
||||||
# dec(ex)
|
|
||||||
|
|
||||||
proc `^`*(left: Int256, right: int): Int256 =
|
|
||||||
var value = right.i256
|
|
||||||
result = 1.i256
|
|
||||||
var m = right.i256
|
|
||||||
while value > 0.i256:
|
|
||||||
result = result * m
|
|
||||||
value -= 1.i256
|
|
||||||
|
|
||||||
proc `^`*(left: UInt256, right: UInt256): UInt256 =
|
|
||||||
var value = right
|
|
||||||
result = 1.u256
|
|
||||||
var m = right.u256
|
|
||||||
while value > 0.u256:
|
|
||||||
result = result * m
|
|
||||||
value -= 1.u256
|
|
||||||
|
|
||||||
proc `^`*(left: UInt256, right: int): UInt256 =
|
|
||||||
left ^ right.u256
|
|
||||||
|
|
||||||
proc `>`*(a: Int256, b: int): bool =
|
|
||||||
a > b.i256
|
|
||||||
|
|
||||||
proc `<`*(a: Int256, b: int): bool =
|
|
||||||
a < b.i256
|
|
||||||
|
|
||||||
proc `>`*(a: UInt256, b: int): bool =
|
|
||||||
a > b.u256
|
|
||||||
|
|
||||||
proc `<`*(a: UInt256, b: int): bool =
|
|
||||||
a < b.u256
|
|
||||||
|
|
||||||
proc `mod`*(a: Int256, b: int): Int256 =
|
|
||||||
a mod b.i256
|
|
||||||
|
|
||||||
proc `div`*(a: Int256, b: int): Int256 =
|
|
||||||
a div b.i256
|
|
||||||
|
|
||||||
proc `mod`*(a: UInt256, b: int): UInt256 =
|
|
||||||
a mod b.u256
|
|
||||||
|
|
||||||
proc `div`*(a: UInt256, b: int): UInt256 =
|
|
||||||
a div b.u256
|
|
||||||
|
|
||||||
template mapOp(op: untyped): untyped =
|
|
||||||
proc `op`*(left: Int256, right: int): Int256 =
|
|
||||||
result = left.i256
|
|
||||||
result = `op`(result, right.i256)
|
|
||||||
|
|
||||||
proc `op`*(left: UInt256, right: int): UInt256 =
|
|
||||||
result = left.u256
|
|
||||||
result = `op`(result, right.u256)
|
|
||||||
|
|
||||||
mapOp(`and`)
|
|
||||||
mapOp(`or`)
|
|
||||||
mapOp(`xor`)
|
|
||||||
|
|
||||||
proc default(t: typedesc): t = discard
|
proc default(t: typedesc): t = discard
|
||||||
|
|
||||||
# constants
|
# constants
|
||||||
|
@ -108,7 +11,7 @@ let
|
||||||
INT_256_MAX_AS_UINT256* = cast[Uint256](high(Int256))
|
INT_256_MAX_AS_UINT256* = cast[Uint256](high(Int256))
|
||||||
NULLBYTE* = "\x00"
|
NULLBYTE* = "\x00"
|
||||||
EMPTYWORD* = repeat(NULLBYTE, 32)
|
EMPTYWORD* = repeat(NULLBYTE, 32)
|
||||||
UINT160CEILING*: UInt256 = 2.u256 ^ 160
|
UINT160CEILING*: UInt256 = 2.u256.pow(160)
|
||||||
ZERO_ADDRESS* = default(EthAddress)
|
ZERO_ADDRESS* = default(EthAddress)
|
||||||
CREATE_CONTRACT_ADDRESS* = ZERO_ADDRESS
|
CREATE_CONTRACT_ADDRESS* = ZERO_ADDRESS
|
||||||
ZERO_HASH32* = Hash256()
|
ZERO_HASH32* = Hash256()
|
||||||
|
@ -133,14 +36,6 @@ let
|
||||||
MAX_UNCLE_DEPTH* = 6.u256
|
MAX_UNCLE_DEPTH* = 6.u256
|
||||||
MAX_UNCLES* = 2.u256
|
MAX_UNCLES* = 2.u256
|
||||||
|
|
||||||
SECPK1_P*: UInt256 = 2.u256 ^ 256 - 2.u256 ^ 32 - 977.u256
|
|
||||||
SECPK1_N*: UInt256 = "115792089237316195423570985008687907852837564279074904382605163141518161494337".u256
|
|
||||||
SECPK1_A* = 0.u256
|
|
||||||
SECPK1_B* = 7.u256
|
|
||||||
SECPK1_Gx* = 0.u256
|
|
||||||
SECPK1_Gy* = 0.u256
|
|
||||||
SECPK1_G* = (SECPK1Gx, SECPK1Gy)
|
|
||||||
|
|
||||||
EMPTY_UNCLE_HASH* = "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".toDigest
|
EMPTY_UNCLE_HASH* = "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".toDigest
|
||||||
|
|
||||||
GENESIS_BLOCK_NUMBER* = 0.u256
|
GENESIS_BLOCK_NUMBER* = 0.u256
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
eth_common, tables,
|
eth_common, tables, nimcrypto, stint, rlp,
|
||||||
../constants, ../errors, ../validation, ../account, ../logging, ../utils_numeric, .. / utils / [padding, bytes, keccak],
|
../constants, ../errors, ../validation, ../account, ../logging
|
||||||
stint, rlp
|
|
||||||
|
|
||||||
type
|
type
|
||||||
AccountStateDB* = ref object
|
AccountStateDB* = ref object
|
||||||
|
@ -64,11 +63,11 @@ proc setStorage*(db: var AccountStateDB, address: EthAddress, slot: UInt256, val
|
||||||
# let account = db.getAccount(address)
|
# let account = db.getAccount(address)
|
||||||
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
|
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
|
||||||
|
|
||||||
let slotAsKey = slot.intToBigEndian.pad32.toString
|
let slotAsKey = "0x" & slot.dumpHex # Convert to a number to hex big-endian representation including prefix and leading zeros
|
||||||
var storage = db.db
|
var storage = db.db
|
||||||
# TODO fix
|
# TODO fix
|
||||||
if value > 0:
|
if value > 0:
|
||||||
let encodedValue = rlp.encode value.intToBigEndian
|
let encodedValue = rlp.encode value.toByteArrayBE
|
||||||
storage[slotAsKey] = encodedValue
|
storage[slotAsKey] = encodedValue
|
||||||
else:
|
else:
|
||||||
storage.del(slotAsKey)
|
storage.del(slotAsKey)
|
||||||
|
@ -87,13 +86,11 @@ proc getStorage*(db: var AccountStateDB, address: EthAddress, slot: UInt256): (U
|
||||||
# let account = db.GetAccount(address)
|
# let account = db.GetAccount(address)
|
||||||
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
|
# var storage = HashTrie(HexaryTrie(self.db, account.storageRoot))
|
||||||
|
|
||||||
let slotAsKey = slot.intToBigEndian.pad32.toString
|
let slotAsKey = "0x" & slot.dumpHex # Convert to a number to hex big-endian representation including prefix and leading zeros
|
||||||
var storage = db.db
|
var storage = db.db
|
||||||
if storage.hasKey(slotAsKey):
|
if storage.hasKey(slotAsKey):
|
||||||
#result = storage[slotAsKey]
|
let byteRange = storage[slotAsKey]
|
||||||
# XXX: `bigEndianToInt` can be refactored to work with a BytesRange/openarray
|
result = (readUintBE[256](byteRange.toOpenArray), true)
|
||||||
# Then we won't need to call `toSeq` here.
|
|
||||||
result = (storage[slotAsKey].toSeq.bigEndianToInt, true)
|
|
||||||
else:
|
else:
|
||||||
result = (0.u256, false)
|
result = (0.u256, false)
|
||||||
|
|
||||||
|
@ -117,7 +114,7 @@ proc setCode*(db: var AccountStateDB, address: EthAddress, code: string) =
|
||||||
|
|
||||||
var account = db.getAccount(address)
|
var account = db.getAccount(address)
|
||||||
|
|
||||||
account.codeHash = keccak(code)
|
account.codeHash = keccak256.digest code
|
||||||
#db.db[account.codeHash] = code
|
#db.db[account.codeHash] = code
|
||||||
db.setAccount(address, account)
|
db.setAccount(address, account)
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ type
|
||||||
## Error signaling that an account has insufficient funds to transfer the
|
## Error signaling that an account has insufficient funds to transfer the
|
||||||
## requested value.
|
## requested value.
|
||||||
|
|
||||||
StackDepthLimit* = object of VMError
|
StackDepthError* = object of VMError
|
||||||
## Error signaling that the call stack has exceeded it's maximum allowed depth.
|
## Error signaling that the call stack has exceeded it's maximum allowed depth.
|
||||||
|
|
||||||
ContractCreationCollision* = object of VMError
|
ContractCreationCollision* = object of VMError
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
# --warning[XDeclaredButNotUsed]:off
|
|
|
@ -1,34 +0,0 @@
|
||||||
# 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
|
|
||||||
strformat, strutils, sequtils, macros,
|
|
||||||
constants, logging, errors, opcode_values, computation, vm/stack, stint,
|
|
||||||
./vm_types
|
|
||||||
|
|
||||||
|
|
||||||
# Super dirty fix for https://github.com/status-im/nimbus/issues/46
|
|
||||||
# Pending https://github.com/status-im/nimbus/issues/36
|
|
||||||
# Disentangle opcode logic
|
|
||||||
from logic.call import runLogic, BaseCall
|
|
||||||
|
|
||||||
|
|
||||||
template run*(opcode: Opcode, computation: var BaseComputation) =
|
|
||||||
# Hook for performing the actual VM execution
|
|
||||||
# opcode.consumeGas(computation)
|
|
||||||
|
|
||||||
if opcode.kind == Op.Call: # Super dirty fix for https://github.com/status-im/nimbus/issues/46
|
|
||||||
# TODO remove this branch
|
|
||||||
runLogic(BaseCall(opcode), computation)
|
|
||||||
elif computation.gasCosts[opcode.kind].kind != GckFixed:
|
|
||||||
opcode.runLogic(computation)
|
|
||||||
else:
|
|
||||||
computation.gasMeter.consumeGas(computation.gasCosts[opcode.kind].cost, reason = $opcode.kind)
|
|
||||||
opcode.runLogic(computation)
|
|
||||||
|
|
||||||
method logger*(opcode: Opcode): Logger =
|
|
||||||
logging.getLogger(&"vm.opcode.{opcode.kind}")
|
|
|
@ -1,93 +0,0 @@
|
||||||
# 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
|
|
||||||
strformat, strutils, tables, macros,
|
|
||||||
constants, stint, errors, logging, vm_state, opcode_table,
|
|
||||||
vm / [gas_meter, stack, code_stream, memory, message, value], db / chain, computation, opcode, opcode_values, utils / [header, address],
|
|
||||||
logic / [arithmetic, comparison, sha3, context, block_ops, stack_ops, duplication, swap, memory_ops, storage, flow, logging_ops, invalid, call, system_ops]
|
|
||||||
|
|
||||||
var mem = newMemory(pow(1024.int256, 2))
|
|
||||||
|
|
||||||
var to = toCanonicalAddress("0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6")
|
|
||||||
var sender = toCanonicalAddress("0xcd1722f3947def4cf144679da39c4c32bdc35681")
|
|
||||||
|
|
||||||
var code = ""
|
|
||||||
var data: seq[byte] = @[]
|
|
||||||
|
|
||||||
var msg = newMessage(
|
|
||||||
25.int256,
|
|
||||||
1.int256,
|
|
||||||
to,
|
|
||||||
sender,
|
|
||||||
0.int256,
|
|
||||||
data,
|
|
||||||
code,
|
|
||||||
MessageOptions(depth: 1))
|
|
||||||
|
|
||||||
var c = BaseComputation(
|
|
||||||
vmState: BaseVMState(
|
|
||||||
prevHeaders: @[],
|
|
||||||
chaindb: BaseChainDB(),
|
|
||||||
blockHeader: BlockHeader(),
|
|
||||||
name: "zero"),
|
|
||||||
msg: msg,
|
|
||||||
memory: mem,
|
|
||||||
stack: newStack(),
|
|
||||||
gasMeter: newGasMeter(msg.gas),
|
|
||||||
code: newCodeStream(code),
|
|
||||||
children: @[],
|
|
||||||
rawOutput: "",
|
|
||||||
returnData: "",
|
|
||||||
error: nil,
|
|
||||||
logEntries: @[],
|
|
||||||
shouldEraseReturnData: false,
|
|
||||||
accountsToDelete: initTable[string, string](),
|
|
||||||
opcodes: OPCODE_TABLE,
|
|
||||||
precompiles: initTable[string, Opcode]())
|
|
||||||
|
|
||||||
# var c2 = c.applyComputation(c.vmState, c.msg)
|
|
||||||
|
|
||||||
macro runOpcodes*(computation: untyped, program: untyped): untyped =
|
|
||||||
# runOpcodes(c):
|
|
||||||
# stack: @[Value..]
|
|
||||||
#
|
|
||||||
# Op
|
|
||||||
# Op
|
|
||||||
#
|
|
||||||
# becomes
|
|
||||||
#
|
|
||||||
# c.stack.push(Value) ..
|
|
||||||
#
|
|
||||||
# c.getOpcodeFn(Op).run(c)
|
|
||||||
# echo c.stack ..
|
|
||||||
var stack = nnkStmtList.newTree()
|
|
||||||
for child in program[0][1][0][1]:
|
|
||||||
let push = quote:
|
|
||||||
`computation`.stack.push(`child`)
|
|
||||||
stack.add(push)
|
|
||||||
|
|
||||||
var ops = nnkStmtList.newTree()
|
|
||||||
for z, op in program:
|
|
||||||
if z > 0:
|
|
||||||
let run = quote:
|
|
||||||
`computation`.getOpcodeFn(`op`).run(`computation`)
|
|
||||||
echo `computation`.stack
|
|
||||||
ops.add(run)
|
|
||||||
|
|
||||||
result = nnkStmtList.newTree(stack, ops)
|
|
||||||
|
|
||||||
# useful for testing simple cases
|
|
||||||
runOpcodes(c):
|
|
||||||
stack: @[2.vint, 2.vint, 2.vint, 2.vint, 2.vint, 2.vint, 4.vint]
|
|
||||||
|
|
||||||
Op.Add
|
|
||||||
Op.Mul
|
|
||||||
Op.Div
|
|
||||||
Op.Sub
|
|
||||||
Op.Mul
|
|
||||||
|
|
|
@ -24,5 +24,3 @@ proc toString*(value: seq[byte]): string =
|
||||||
|
|
||||||
proc toBytes*(value: string): seq[byte] =
|
proc toBytes*(value: string): seq[byte] =
|
||||||
result = value.mapIt(it.byte)
|
result = value.mapIt(it.byte)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -92,4 +92,8 @@ proc generateHeaderFromParentHeader*(
|
||||||
# TODO: data: extraData,
|
# TODO: data: extraData,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import nimcrypto
|
||||||
|
# TODO: required otherwise
|
||||||
|
# eth_common/rlp_serialization.nim(18, 12) template/generic instantiation from here
|
||||||
|
# nimcrypto/hash.nim(46, 6) Error: attempting to call undeclared routine: 'init'
|
||||||
proc hash*(b: BlockHeader): Hash256 {.inline.} = rlpHash(b)
|
proc hash*(b: BlockHeader): Hash256 {.inline.} = rlpHash(b)
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# 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_utils, rlp, trie, evm.db.backends.memory, evm.db.chain
|
|
||||||
|
|
||||||
# proc makeTrieRootAndNodes*(transactions: auto; trieClass: auto): auto =
|
|
||||||
# var
|
|
||||||
# chaindb = BaseChainDB(MemoryDB())
|
|
||||||
# db = chaindb.db
|
|
||||||
# transactionDb = trieClass(db)
|
|
||||||
# for index, transaction in transactions:
|
|
||||||
# var indexKey = rlp.encode(index)
|
|
||||||
# transactionDb[indexKey] = rlp.encode(transaction)
|
|
||||||
# return (transactionDb.rootHash, transactionDb.db.wrappedDb.kvStore)
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../logging, ../constants, ../errors, ../transaction, ../vm_types, ../computation, ../block_types, ../vm_state, ../vm_state_transactions, ../db/db_chain, ../utils/header
|
../logging, ../constants, ../errors, ../transaction, ../vm_types,
|
||||||
|
../block_types, ../vm_state, ../vm_state_transactions, ../db/db_chain, ../utils/header,
|
||||||
|
./computation
|
||||||
|
|
||||||
type
|
type
|
||||||
VMkind* = enum
|
VMkind* = enum
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, strutils, sequtils, parseutils, sets, macros,
|
strformat, strutils, sequtils, parseutils, sets, macros,
|
||||||
../logging, ../constants, ../opcode_values
|
../logging, ../constants, ./interpreter/opcode_values
|
||||||
|
|
||||||
type
|
type
|
||||||
CodeStream* = ref object
|
CodeStream* = ref object
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, strutils, sequtils, macros, stint, terminal, math, eth_common, byteutils, tables,
|
strformat, strutils, sequtils, macros, stint, terminal, math, eth_common, byteutils, tables,
|
||||||
./constants, ./errors, ./utils/hexadecimal, ./utils_numeric, ./validation, ./vm_state, ./logging, ./opcode_values, ./vm_types,
|
../constants, ../errors, ../validation, ../vm_state, ../logging, ../vm_types,
|
||||||
./vm/[code_stream, gas_meter, memory, message, stack],
|
./interpreter/[opcode_values,gas_meter, gas_costs],
|
||||||
|
./code_stream, ./memory, ./message, ./stack,
|
||||||
|
|
||||||
# TODO further refactoring of gas cost
|
# TODO further refactoring of gas cost
|
||||||
vm/forks/gas_costs,
|
./forks/f20150730_frontier/frontier_vm_state,
|
||||||
vm/forks/f20150730_frontier/frontier_vm_state,
|
./forks/f20161018_tangerine_whistle/tangerine_vm_state
|
||||||
vm/forks/f20161018_tangerine_whistle/tangerine_vm_state
|
|
||||||
|
|
||||||
method newBaseComputation*(vmState: BaseVMState, message: Message): BaseComputation {.base.}=
|
method newBaseComputation*(vmState: BaseVMState, message: Message): BaseComputation {.base.}=
|
||||||
raise newException(ValueError, "Must be implemented by subclasses")
|
raise newException(ValueError, "Must be implemented by subclasses")
|
||||||
|
@ -239,6 +239,27 @@ method getOpcodeFn*(computation: var BaseComputation, op: Op): Opcode =
|
||||||
raise newException(InvalidInstruction,
|
raise newException(InvalidInstruction,
|
||||||
&"Invalid opcode {op}")
|
&"Invalid opcode {op}")
|
||||||
|
|
||||||
|
# Super dirty fix for https://github.com/status-im/nimbus/issues/46
|
||||||
|
# Pending https://github.com/status-im/nimbus/issues/36
|
||||||
|
# Disentangle opcode logic
|
||||||
|
from ./interpreter/opcodes_impl/call import runLogic, BaseCall
|
||||||
|
|
||||||
|
template run*(opcode: Opcode, computation: var BaseComputation) =
|
||||||
|
# Hook for performing the actual VM execution
|
||||||
|
# opcode.consumeGas(computation)
|
||||||
|
|
||||||
|
if opcode.kind == Op.Call: # Super dirty fix for https://github.com/status-im/nimbus/issues/46
|
||||||
|
# TODO remove this branch
|
||||||
|
runLogic(BaseCall(opcode), computation)
|
||||||
|
elif computation.gasCosts[opcode.kind].kind != GckFixed:
|
||||||
|
opcode.runLogic(computation)
|
||||||
|
else:
|
||||||
|
computation.gasMeter.consumeGas(computation.gasCosts[opcode.kind].cost, reason = $opcode.kind)
|
||||||
|
opcode.runLogic(computation)
|
||||||
|
|
||||||
|
method logger*(opcode: Opcode): Logger =
|
||||||
|
logging.getLogger(&"vm.opcode.{opcode.kind}")
|
||||||
|
|
||||||
macro applyComputation*(t: typed, vmState: untyped, message: untyped): untyped =
|
macro applyComputation*(t: typed, vmState: untyped, message: untyped): untyped =
|
||||||
# Perform the computation that would be triggered by the VM message
|
# Perform the computation that would be triggered by the VM message
|
||||||
# c.applyComputation(vmState, message)
|
# c.applyComputation(vmState, message)
|
|
@ -0,0 +1 @@
|
||||||
|
Folder to be deleted
|
|
@ -5,14 +5,20 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import strutils
|
import
|
||||||
|
./interpreter/[opcode_values, gas_meter, opcode_table],
|
||||||
|
./interpreter/vm_forks
|
||||||
|
|
||||||
# proc encodeHex*(value: string): string =
|
from utils/utils_numeric import bigEndianToInt
|
||||||
# # return "0x" & codecs.decode(codecs.encode(value, "hex"), "utf8")
|
|
||||||
# return value
|
|
||||||
|
|
||||||
# proc decodeHex*(value: string): string =
|
import # Used in vm_types. Beware of recursive dependencies
|
||||||
# # var hexPart = value.rsplit("x", 1)[1]
|
./code_stream, ./computation, ./stack, ./message
|
||||||
# return value
|
|
||||||
# # return codecs.decode(hexPart, "hex")
|
|
||||||
|
|
||||||
|
export
|
||||||
|
opcode_values, gas_meter, opcode_table,
|
||||||
|
vm_forks
|
||||||
|
|
||||||
|
export utils_numeric.bigEndianToInt
|
||||||
|
|
||||||
|
export
|
||||||
|
code_stream, computation, stack, message
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
@ -6,10 +6,9 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
stint, eth_common, math,
|
stint, math, eth_common, # GasInt
|
||||||
../../utils/macros_gen_opcodes,
|
../utils/[macros_gen_opcodes, utils_numeric],
|
||||||
../../opcode_values,
|
./opcode_values
|
||||||
../../utils_numeric
|
|
||||||
|
|
||||||
# Gas Fee Schedule
|
# Gas Fee Schedule
|
||||||
# Yellow Paper Appendix G - https://ethereum.github.io/yellowpaper/paper.pdf
|
# Yellow Paper Appendix G - https://ethereum.github.io/yellowpaper/paper.pdf
|
|
@ -6,8 +6,8 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat,
|
strformat, eth_common, # GasInt
|
||||||
../logging, ../errors, ../vm_types
|
../../logging, ../../errors, ../../vm_types
|
||||||
|
|
||||||
proc newGasMeter*(startGas: GasInt): GasMeter =
|
proc newGasMeter*(startGas: GasInt): GasMeter =
|
||||||
new(result)
|
new(result)
|
|
@ -6,11 +6,9 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
tables,
|
tables, stint,
|
||||||
stint, logging,
|
../../vm_types, ./opcode_values,
|
||||||
vm / [gas_meter, stack, code_stream, memory, message], db / db_chain, computation, opcode, opcode_values, utils / [header, address],
|
opcodes_impl/[arithmetic, comparison, sha3, context, block_ops, stack_ops, duplication, swap, memory_ops, storage, flow, logging_ops, invalid, call, system_ops]
|
||||||
logic / [arithmetic, comparison, sha3, context, block_ops, stack_ops, duplication, swap, memory_ops, storage, flow, logging_ops, invalid, call, system_ops],
|
|
||||||
./vm_types
|
|
||||||
|
|
||||||
const
|
const
|
||||||
OpLogic*: Table[Op, proc(computation: var BaseComputation){.nimcall.}] = {
|
OpLogic*: Table[Op, proc(computation: var BaseComputation){.nimcall.}] = {
|
|
@ -5,7 +5,7 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import ./utils/macros_gen_opcodes
|
import ../utils/macros_gen_opcodes
|
||||||
|
|
||||||
fill_enum_holes:
|
fill_enum_holes:
|
||||||
type
|
type
|
|
@ -6,9 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../constants, ../utils_numeric, ../computation, ../vm_types,
|
helpers, stint, strutils, ./impl_std_import
|
||||||
.. / vm / [gas_meter, stack], ../opcode, ../opcode_values,
|
|
||||||
helpers, stint, strutils
|
|
||||||
|
|
||||||
proc add*(computation: var BaseComputation) =
|
proc add*(computation: var BaseComputation) =
|
||||||
# Addition
|
# Addition
|
||||||
|
@ -107,7 +105,7 @@ proc signextend*(computation: var BaseComputation) =
|
||||||
if bits <= 31.u256:
|
if bits <= 31.u256:
|
||||||
let testBit = bits.toInt * 8 + 7
|
let testBit = bits.toInt * 8 + 7
|
||||||
let bitPos = (1 shl testBit)
|
let bitPos = (1 shl testBit)
|
||||||
let mask = bitPos - 1
|
let mask = u256(bitPos - 1)
|
||||||
if not (value and bitPos).isZero:
|
if not (value and bitPos).isZero:
|
||||||
res = value or (not mask)
|
res = value or (not mask)
|
||||||
else:
|
else:
|
|
@ -6,8 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
times,
|
times, ./impl_std_import
|
||||||
../constants, ../errors, ../computation, ../vm_state, ../vm_types, .. / vm / [stack], stint
|
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
{.experimental.}
|
{.experimental.}
|
|
@ -6,11 +6,15 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, eth_common,
|
strformat, eth_common, stint,
|
||||||
../constants, ../vm_types, ../errors, ../computation, ../opcode_values, ../logging,
|
# ./impl_std_import # Cannot do that due to recursive dependencies
|
||||||
.. / vm / [stack, memory, gas_meter, message],
|
# .../vm/interpreter/opcodes_impl/impl_std_import.nim imports .../vm/computation.nim
|
||||||
.. / utils / [address, bytes],
|
# .../vm/computation.nim imports .../vm/interpreter/opcodes_impl/call.nim
|
||||||
stint
|
# .../vm/interpreter/opcodes_impl/call.nim imports .../vm/interpreter/opcodes_impl/impl_std_import.nim
|
||||||
|
../../../constants, ../../../vm_types, ../../../errors, ../../../logging,
|
||||||
|
../../../utils/bytes,
|
||||||
|
../../computation, ../../stack, ../../memory, ../../message,
|
||||||
|
../opcode_values, ../gas_meter, ../gas_costs
|
||||||
|
|
||||||
type
|
type
|
||||||
# TODO most of these are for gas handling
|
# TODO most of these are for gas handling
|
||||||
|
@ -68,7 +72,7 @@ method runLogic*(call: BaseCall, computation) =
|
||||||
let senderBalance = 0.u256
|
let senderBalance = 0.u256
|
||||||
|
|
||||||
let insufficientFunds = shouldTransferValue and senderBalance < value
|
let insufficientFunds = shouldTransferValue and senderBalance < value
|
||||||
let stackTooDeep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT
|
let stackTooDeep = computation.msg.depth + 1 > STACK_DEPTH_LIMIT
|
||||||
|
|
||||||
if insufficientFunds or stackTooDeep:
|
if insufficientFunds or stackTooDeep:
|
||||||
computation.returnData = ""
|
computation.returnData = ""
|
|
@ -6,8 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../constants, ../utils_numeric, ../computation, ../vm/stack, ../vm_types,
|
helpers, ./impl_std_import
|
||||||
helpers, stint
|
|
||||||
|
|
||||||
quasiBoolean(lt, `<`) # Lesser Comparison
|
quasiBoolean(lt, `<`) # Lesser Comparison
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ proc iszero*(computation: var BaseComputation) =
|
||||||
proc notOp*(computation: var BaseComputation) =
|
proc notOp*(computation: var BaseComputation) =
|
||||||
var value = computation.stack.popInt()
|
var value = computation.stack.popInt()
|
||||||
|
|
||||||
var res = constants.UINT_256_MAX - value
|
var res = UINT_256_MAX - value
|
||||||
pushRes()
|
pushRes()
|
||||||
|
|
||||||
# TODO: seems like there is an implementation or a comment issue
|
# TODO: seems like there is an implementation or a comment issue
|
|
@ -7,9 +7,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat,
|
strformat,
|
||||||
../constants, ../vm_types, ../errors, ../utils_numeric, ../computation, ../vm_state, ../account, ../db/state_db, ../validation,
|
./impl_std_import
|
||||||
.. /vm/[stack, message, gas_meter, memory, code_stream], ../utils/[address, padding, bytes], stint,
|
|
||||||
../opcode_values
|
|
||||||
|
|
||||||
proc balance*(computation: var BaseComputation) =
|
proc balance*(computation: var BaseComputation) =
|
||||||
let address = computation.stack.popAddress()
|
let address = computation.stack.popAddress()
|
|
@ -6,8 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
macros, strformat,
|
macros, strformat, ./impl_std_import
|
||||||
../vm_types, ../computation, ../vm/stack
|
|
||||||
|
|
||||||
macro dupXX(position: static[int]): untyped =
|
macro dupXX(position: static[int]): untyped =
|
||||||
let name = ident(&"dup{position}")
|
let name = ident(&"dup{position}")
|
|
@ -6,9 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, stint,
|
strformat, ./impl_std_import
|
||||||
../constants, ../vm_types, ../opcode_values, ../logging, ../errors, ../computation, .. /vm / [code_stream, stack]
|
|
||||||
|
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
{.experimental.}
|
{.experimental.}
|
|
@ -5,7 +5,7 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import macros
|
import macros, stint
|
||||||
|
|
||||||
template pushRes*: untyped =
|
template pushRes*: untyped =
|
||||||
computation.stack.push(res)
|
computation.stack.push(res)
|
||||||
|
@ -22,8 +22,8 @@ macro quasiBoolean*(name: untyped, op: untyped, signed: untyped = nil, nonzero:
|
||||||
actualLeftNode = ident("leftSigned")
|
actualLeftNode = ident("leftSigned")
|
||||||
actualRightNode = ident("rightSigned")
|
actualRightNode = ident("rightSigned")
|
||||||
signedNode = quote:
|
signedNode = quote:
|
||||||
let `actualLeftNode` = unsignedToSigned(`leftNode`)
|
let `actualLeftNode` = cast[Int256](`leftNode`)
|
||||||
let `actualRightNode` = unsignedToSigned(`rightNode`)
|
let `actualRightNode` = cast[Int256](`rightNode`)
|
||||||
var test = if nonzero.isNil:
|
var test = if nonzero.isNil:
|
||||||
quote:
|
quote:
|
||||||
`op`(`actualLeftNode`, `actualRightNode`)
|
`op`(`actualLeftNode`, `actualRightNode`)
|
|
@ -0,0 +1,22 @@
|
||||||
|
# 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
|
||||||
|
stint, stint/lenient_stint,
|
||||||
|
../../../constants, ../../../vm_state, ../../../vm_types, ../../../vm_types,
|
||||||
|
../../../errors, ../../../logging, ../../../utils/padding, ../../../utils/bytes,
|
||||||
|
../../stack, ../../computation, ../../stack, ../../memory, ../../message,
|
||||||
|
../../code_stream, ../../utils/utils_numeric,
|
||||||
|
../opcode_values, ../gas_meter, ../gas_costs
|
||||||
|
|
||||||
|
export
|
||||||
|
stint, lenient_stint,
|
||||||
|
constants, vm_state, vm_types, vm_types,
|
||||||
|
errors, logging, padding, bytes,
|
||||||
|
stack, computation, stack, memory, message,
|
||||||
|
code_stream, utils_numeric,
|
||||||
|
opcode_values, gas_meter, gas_costs
|
|
@ -6,7 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../errors, ../vm_types, ../computation
|
./impl_std_import
|
||||||
|
|
||||||
proc invalidOp*(computation: var BaseComputation) =
|
proc invalidOp*(computation: var BaseComputation) =
|
||||||
raise newException(InvalidInstruction, "Invalid opcode")
|
raise newException(InvalidInstruction, "Invalid opcode")
|
|
@ -7,9 +7,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, macros,
|
strformat, macros,
|
||||||
../constants, ../errors, ../vm_types, ../computation, ../vm/[stack, memory, gas_meter, message], ../utils/bytes,
|
./impl_std_import
|
||||||
../opcode_values,
|
|
||||||
stint
|
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
{.experimental.}
|
{.experimental.}
|
||||||
|
@ -53,7 +51,7 @@ macro logXX(topicCount: static[int]): untyped =
|
||||||
result.body.add(topicCode)
|
result.body.add(topicCode)
|
||||||
|
|
||||||
let OpName = ident(&"Log{topicCount}")
|
let OpName = ident(&"Log{topicCount}")
|
||||||
let logicCode = quote:
|
let logicCode = quote do:
|
||||||
`computation`.gasMeter.consumeGas(
|
`computation`.gasMeter.consumeGas(
|
||||||
`computation`.gasCosts[`OpName`].m_handler(`computation`.memory.len, `memPos`, `len`),
|
`computation`.gasCosts[`OpName`].m_handler(`computation`.memory.len, `memPos`, `len`),
|
||||||
reason="Memory expansion, Log topic and data gas cost")
|
reason="Memory expansion, Log topic and data gas cost")
|
||||||
|
@ -65,7 +63,6 @@ macro logXX(topicCount: static[int]): untyped =
|
||||||
data = log_data)
|
data = log_data)
|
||||||
|
|
||||||
result.body.add(logicCode)
|
result.body.add(logicCode)
|
||||||
# echo result.repr
|
|
||||||
|
|
||||||
logXX(0)
|
logXX(0)
|
||||||
logXX(1)
|
logXX(1)
|
|
@ -6,10 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../constants, ../computation, ../vm_types, ../vm/[stack, memory, gas_meter], .. /utils/[padding, bytes],
|
./impl_std_import
|
||||||
../opcode_values,
|
|
||||||
stint
|
|
||||||
|
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
{.experimental.}
|
{.experimental.}
|
|
@ -6,21 +6,19 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../constants, ../utils_numeric, ../utils/[keccak, bytes], ../vm/[stack, memory, gas_meter],
|
nimcrypto,
|
||||||
../computation, ../vm_types, ../opcode_values,
|
./impl_std_import, ./helpers
|
||||||
./helpers,
|
|
||||||
stint
|
|
||||||
|
|
||||||
proc sha3op*(computation: var BaseComputation) =
|
proc sha3op*(computation: var BaseComputation) =
|
||||||
let (startPosition, size) = computation.stack.popInt(2)
|
let (startPosition, size) = computation.stack.popInt(2)
|
||||||
let (pos, len) = (startPosition.toInt, size.toInt)
|
let (pos, len) = (startPosition.toInt, size.toInt)
|
||||||
|
|
||||||
computation.gasMeter.consumeGas(
|
computation.gasMeter.consumeGas(
|
||||||
computation.gasCosts[Sha3].m_handler(computation.memory.len, pos, len),
|
computation.gasCosts[Op.Sha3].m_handler(computation.memory.len, pos, len),
|
||||||
reason="SHA3: word gas cost"
|
reason="SHA3: word gas cost"
|
||||||
)
|
)
|
||||||
|
|
||||||
computation.memory.extend(pos, len)
|
computation.memory.extend(pos, len)
|
||||||
|
|
||||||
var res = keccak("") # TODO: stub
|
var res = keccak256.digest("") # TODO: stub
|
||||||
pushRes()
|
pushRes()
|
|
@ -6,8 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, macros, sequtils,
|
strformat, macros, ./impl_std_import
|
||||||
../vm_types, ../constants, ../errors, ../computation, .. / vm / [stack, code_stream], .. / utils / [padding, bytes], stint
|
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
{.experimental.}
|
{.experimental.}
|
|
@ -6,11 +6,10 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
../constants, ../vm_types, ../errors, ../computation, ../vm_state,
|
./impl_std_import, strformat,
|
||||||
../utils/header,
|
../../../utils/header,
|
||||||
../db/[db_chain, state_db], ../vm/[stack, gas_meter, message],
|
../../../db/[db_chain, state_db]
|
||||||
../opcode_values,
|
|
||||||
strformat, stint
|
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
{.experimental.}
|
{.experimental.}
|
|
@ -6,8 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
macros, strformat,
|
macros, strformat, ./impl_std_import
|
||||||
../vm_types, ../computation, ../vm/stack
|
|
||||||
|
|
||||||
macro swapXX(position: static[int]): untyped =
|
macro swapXX(position: static[int]): untyped =
|
||||||
let name = ident(&"swap{position}")
|
let name = ident(&"swap{position}")
|
|
@ -7,9 +7,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat,
|
strformat,
|
||||||
../constants, ../vm_types, ../errors, ../computation, ../opcode, ../opcode_values, ../logging, ../vm_state, call,
|
./call, ./impl_std_import,
|
||||||
.. / vm / [stack, gas_meter, memory, message], .. / utils / [address, hexadecimal, bytes],
|
|
||||||
../opcode_values,
|
|
||||||
stint, byteutils, eth_common
|
stint, byteutils, eth_common
|
||||||
|
|
||||||
{.this: computation.}
|
{.this: computation.}
|
||||||
|
@ -70,7 +68,7 @@ method runLogic*(create: Create, computation) =
|
||||||
|
|
||||||
let childMsg = computation.prepareChildMessage(
|
let childMsg = computation.prepareChildMessage(
|
||||||
gas=0, # TODO refactor gas
|
gas=0, # TODO refactor gas
|
||||||
to=constants.CREATE_CONTRACT_ADDRESS,
|
to=CREATE_CONTRACT_ADDRESS,
|
||||||
value=value,
|
value=value,
|
||||||
data=cast[seq[byte]](@[]),
|
data=cast[seq[byte]](@[]),
|
||||||
code=callData.toString,
|
code=callData.toString,
|
|
@ -9,8 +9,8 @@ import
|
||||||
../../db/db_chain, ../../constants,
|
../../db/db_chain, ../../constants,
|
||||||
../../utils/header,
|
../../utils/header,
|
||||||
../base,
|
../base,
|
||||||
./f20150730_frontier/frontier_vm,
|
../forks/f20150730_frontier/frontier_vm,
|
||||||
./f20161018_tangerine_whistle/tangerine_vm,
|
../forks/f20161018_tangerine_whistle/tangerine_vm,
|
||||||
stint
|
stint
|
||||||
|
|
||||||
# Note (mamy): refactoring is in progress (2018-05-23), this is redundant with
|
# Note (mamy): refactoring is in progress (2018-05-23), this is redundant with
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
sequtils, stint,
|
sequtils, stint,
|
||||||
../constants, ../errors, ../logging, ../validation, ../utils_numeric, ../utils/bytes
|
../constants, ../errors, ../logging, ../validation, ../utils/bytes,
|
||||||
|
./utils/utils_numeric
|
||||||
|
|
||||||
type
|
type
|
||||||
Memory* = ref object
|
Memory* = ref object
|
||||||
|
@ -57,3 +58,7 @@ proc write*(memory: var Memory, startPosition: Natural, value: openarray[byte])
|
||||||
|
|
||||||
template write*(memory: var Memory, startPosition: Natural, size: Natural, value: cstring) =
|
template write*(memory: var Memory, startPosition: Natural, size: Natural, value: cstring) =
|
||||||
memory.write(startPosition, value.toBytes)
|
memory.write(startPosition, value.toBytes)
|
||||||
|
# TODO ~ O(n^3):
|
||||||
|
# - there is a string allocation with $ (?)
|
||||||
|
# - then a conversion to seq (= new allocation) with toBytes
|
||||||
|
# - then writing to memory
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, strutils, sequtils, macros, rlp, eth_common, nimcrypto,
|
strformat, strutils, sequtils, macros, rlp, eth_common, nimcrypto,
|
||||||
../errors, ../validation, ../utils_numeric, ../constants, stint, ../logging, .. / utils / bytes
|
../errors, ../validation, ./utils/utils_numeric, ../constants, stint, ../logging, .. / utils / bytes
|
||||||
|
|
||||||
type
|
type
|
||||||
Stack* = ref object of RootObj
|
Stack* = ref object of RootObj
|
||||||
|
@ -99,6 +99,8 @@ proc swap*(stack: var Stack, position: int) =
|
||||||
raise newException(InsufficientStack,
|
raise newException(InsufficientStack,
|
||||||
&"Insufficient stack items for SWAP{position}")
|
&"Insufficient stack items for SWAP{position}")
|
||||||
|
|
||||||
|
template getint(x: int): int = x
|
||||||
|
|
||||||
proc dup*(stack: var Stack, position: int | UInt256) =
|
proc dup*(stack: var Stack, position: int | UInt256) =
|
||||||
## Perform a DUP operation on the stack
|
## Perform a DUP operation on the stack
|
||||||
let position = position.getInt
|
let position = position.getInt
|
||||||
|
|
|
@ -5,14 +5,12 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import stint, constants, strformat, strutils, sequtils, endians, macros, utils / padding, rlp
|
import
|
||||||
|
stint, strformat, strutils, sequtils, endians, macros, rlp,
|
||||||
|
../../constants, ../../utils/padding
|
||||||
|
|
||||||
# some methods based on py-evm utils/numeric
|
# some methods based on py-evm utils/numeric
|
||||||
|
|
||||||
proc intToBigEndian*(value: UInt256): Bytes {.deprecated.} =
|
|
||||||
result = newSeq[byte](32)
|
|
||||||
result[0 .. ^1] = value.toByteArrayBE()
|
|
||||||
|
|
||||||
proc bigEndianToInt*(value: openarray[byte]): UInt256 =
|
proc bigEndianToInt*(value: openarray[byte]): UInt256 =
|
||||||
if value.len == 32:
|
if value.len == 32:
|
||||||
readUintBE[256](value)
|
readUintBE[256](value)
|
||||||
|
@ -22,14 +20,6 @@ proc bigEndianToInt*(value: openarray[byte]): UInt256 =
|
||||||
proc log256*(value: UInt256): Natural =
|
proc log256*(value: UInt256): Natural =
|
||||||
(255 - value.countLeadingZeroBits) div 8 # Compilers optimize to `shr 3`
|
(255 - value.countLeadingZeroBits) div 8 # Compilers optimize to `shr 3`
|
||||||
|
|
||||||
proc unsignedToSigned*(value: UInt256): Int256 =
|
|
||||||
0.i256
|
|
||||||
# TODO Remove stub (used in quasiBoolean for signed comparison)
|
|
||||||
|
|
||||||
proc signedToUnsigned*(value: Int256): UInt256 =
|
|
||||||
0.u256
|
|
||||||
# TODO Remove stub (used in quasiBoolean for signed comparison)
|
|
||||||
|
|
||||||
proc unsignedToPseudoSigned*(value: UInt256): UInt256 =
|
proc unsignedToPseudoSigned*(value: UInt256): UInt256 =
|
||||||
result = value
|
result = value
|
||||||
if value > INT_256_MAX_AS_UINT256:
|
if value > INT_256_MAX_AS_UINT256:
|
|
@ -9,7 +9,7 @@ import
|
||||||
macros, strformat, tables,
|
macros, strformat, tables,
|
||||||
stint, eth_common,
|
stint, eth_common,
|
||||||
./logging, ./constants, ./errors, ./transaction, ./db/[db_chain, state_db],
|
./logging, ./constants, ./errors, ./transaction, ./db/[db_chain, state_db],
|
||||||
./utils/[state, header]
|
./utils/header
|
||||||
|
|
||||||
type
|
type
|
||||||
BaseVMState* = ref object of RootObj
|
BaseVMState* = ref object of RootObj
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, tables,
|
strformat, tables,
|
||||||
logging, constants, errors, computation, transaction, vm_types, vm_state, block_types, db / db_chain, utils / [state, header]
|
./logging, ./constants, ./errors, ./vm/computation,
|
||||||
|
./transaction, ./vm_types, ./vm_state, ./block_types, ./db/db_chain, ./utils/header
|
||||||
|
|
||||||
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, BlockHeader) {.base.}=
|
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, BlockHeader) {.base.}=
|
||||||
# Execute the transaction in the vm
|
# Execute the transaction in the vm
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
tables,
|
tables, stint, eth_common,
|
||||||
constants, vm_state,
|
./constants, ./vm_state, ./logging,
|
||||||
opcode_values, stint, eth_common,
|
./vm/[memory, stack, code_stream],
|
||||||
vm / [code_stream, memory, stack, forks/gas_costs],
|
./vm/interpreter/[gas_costs, opcode_values] # TODO - will be hidden at a lower layer
|
||||||
./logging
|
|
||||||
|
|
||||||
export GasInt, gas_costs
|
|
||||||
|
|
||||||
type
|
type
|
||||||
BaseComputation* = ref object of RootObj
|
BaseComputation* = ref object of RootObj
|
||||||
|
@ -32,7 +30,7 @@ type
|
||||||
accountsToDelete*: Table[EthAddress, EthAddress]
|
accountsToDelete*: Table[EthAddress, EthAddress]
|
||||||
opcodes*: Table[Op, proc(computation: var BaseComputation){.nimcall.}]
|
opcodes*: Table[Op, proc(computation: var BaseComputation){.nimcall.}]
|
||||||
precompiles*: Table[string, Opcode]
|
precompiles*: Table[string, Opcode]
|
||||||
gasCosts*: GasCosts # TODO - avoid allocating memory for this const
|
gasCosts*: GasCosts # TODO - will be hidden at a lower layer
|
||||||
|
|
||||||
Error* = ref object
|
Error* = ref object
|
||||||
info*: string
|
info*: string
|
||||||
|
|
|
@ -10,5 +10,4 @@ import ./test_code_stream,
|
||||||
./test_memory,
|
./test_memory,
|
||||||
./test_stack,
|
./test_stack,
|
||||||
./test_opcode
|
./test_opcode
|
||||||
# ./test_vm
|
|
||||||
# ./test_vm_json
|
# ./test_vm_json
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
# 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
|
|
||||||
unittest, strformat, tables, times,
|
|
||||||
stint, eth_keys, eth_common,
|
|
||||||
../nimbus/[constants, chain, vm/base, vm/forks/f20150730_frontier/frontier_vm, utils/header, utils/address, db/db_chain, db/backends/memory_backend]
|
|
||||||
|
|
||||||
proc chainWithoutBlockValidation*: Chain =
|
|
||||||
result = configureChain("TestChain", GENESIS_BLOCK_NUMBER, vmkFrontier, false, false)
|
|
||||||
let privateKey = initPrivateKey("45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8")
|
|
||||||
let fundedAddr = privateKey.getPublicKey.toCanonicalAddress
|
|
||||||
let initialBalance = 100_000_000
|
|
||||||
let genesisParams = GenesisParams(
|
|
||||||
blockNumber: GENESIS_BLOCK_NUMBER,
|
|
||||||
difficulty: GENESIS_DIFFICULTY,
|
|
||||||
gasLimit: GENESIS_GAS_LIMIT,
|
|
||||||
parentHash: GENESIS_PARENT_HASH,
|
|
||||||
coinbase: GENESIS_COINBASE,
|
|
||||||
nonce: GENESIS_NONCE,
|
|
||||||
mixHash: GENESIS_MIX_HASH,
|
|
||||||
extraData: GENESIS_EXTRA_DATA,
|
|
||||||
timestamp: fromUnix 1501851927,
|
|
||||||
stateRoot: "9d354f9b5ba851a35eced279ef377111387197581429cfcc7f744ef89a30b5d4".toDigest)
|
|
||||||
let genesisState = {"fundedAddr": FundedAddress(balance: initialBalance.int256, nonce: 0, code: "")}.toTable()
|
|
||||||
result = fromGenesis(
|
|
||||||
result,
|
|
||||||
newBaseChainDB(newMemoryDB()),
|
|
||||||
genesisParams,
|
|
||||||
genesisState)
|
|
||||||
result.fundedAddress = fundedAddr
|
|
||||||
result.fundedAddressInitialBalance = initialBalance
|
|
||||||
result.fundedAddressPrivateKey = privateKey
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, strutils, sequtils,
|
import unittest, strutils, sequtils,
|
||||||
../nimbus/opcode_values, ../nimbus/vm/code_stream
|
../nimbus/vm/interpreter
|
||||||
|
|
||||||
suite "parse bytecode":
|
suite "parse bytecode":
|
||||||
test "accepts bytes":
|
test "accepts bytes":
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, macros, strformat, strutils, sequtils,
|
import unittest, macros, strformat,
|
||||||
stint,
|
stint,
|
||||||
../nimbus/[constants, opcode_values, errors, logging, vm_types, vm/gas_meter]
|
../nimbus/[vm_types, errors, logging, vm/interpreter]
|
||||||
|
|
||||||
# TODO: quicktest
|
# TODO: quicktest
|
||||||
# PS: parametrize can be easily immitated, but still quicktests would be even more useful
|
# PS: parametrize can be easily immitated, but still quicktests would be even more useful
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
import
|
import
|
||||||
os, macros, json, strformat, strutils, parseutils, ospaths, tables,
|
os, macros, json, strformat, strutils, parseutils, ospaths, tables,
|
||||||
stint, byteutils, eth_common, eth_keys,
|
stint, byteutils, eth_common, eth_keys,
|
||||||
../nimbus/utils/[hexadecimal, address, padding],
|
../nimbus/utils/[address, padding],
|
||||||
../nimbus/[chain, vm_state, constants],
|
../nimbus/[vm_state, constants],
|
||||||
../nimbus/db/[db_chain, state_db], ../nimbus/vm/forks/f20150730_frontier/frontier_vm,
|
../nimbus/db/[db_chain, state_db],
|
||||||
../nimbus/vm/base, ../nimbus/transaction
|
../nimbus/vm/base, ../nimbus/transaction
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, macros, strformat, strutils, sequtils,
|
import unittest, sequtils,
|
||||||
stint,
|
stint,
|
||||||
../nimbus/[constants, opcode_values, errors, vm/memory]
|
../nimbus/[constants, errors, vm/memory]
|
||||||
|
|
||||||
proc memory32: Memory =
|
proc memory32: Memory =
|
||||||
result = newMemory()
|
result = newMemory()
|
||||||
|
|
|
@ -7,14 +7,13 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
unittest, stint, tables, parseutils,
|
unittest, stint, tables, parseutils,
|
||||||
../nimbus/[constants, vm_types, errors, logging],
|
../nimbus/[constants, vm_types, logging],
|
||||||
../nimbus/[chain, vm_state, computation, opcode, opcode_table],
|
../nimbus/vm/interpreter,
|
||||||
../nimbus/[utils/header, utils/padding],
|
../nimbus/utils/header,
|
||||||
../nimbus/vm/[gas_meter, message, code_stream, stack],
|
|
||||||
../nimbus/vm/forks/vm_forks,
|
|
||||||
../nimbus/db/[db_chain, state_db, backends/memory_backend],
|
../nimbus/db/[db_chain, state_db, backends/memory_backend],
|
||||||
test_helpers
|
./test_helpers
|
||||||
|
|
||||||
|
from eth_common import GasInt
|
||||||
|
|
||||||
proc testCode(code: string, initialGas: GasInt, blockNum: UInt256): BaseComputation =
|
proc testCode(code: string, initialGas: GasInt, blockNum: UInt256): BaseComputation =
|
||||||
let header = BlockHeader(blockNumber: blockNum)
|
let header = BlockHeader(blockNumber: blockNum)
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
# * 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.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, macros, strformat, strutils, sequtils,
|
import unittest, stint,
|
||||||
stint,
|
../nimbus/[constants, errors, vm/interpreter, utils/bytes]
|
||||||
../nimbus/[constants, opcode_values, errors, utils_numeric, vm/stack, utils/bytes, utils/padding]
|
|
||||||
|
|
||||||
|
|
||||||
template testPush(value: untyped, expected: untyped): untyped =
|
template testPush(value: untyped, expected: untyped): untyped =
|
||||||
|
@ -36,9 +35,6 @@ suite "stack":
|
||||||
expect(FullStack):
|
expect(FullStack):
|
||||||
stack.push(1025)
|
stack.push(1025)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test "dup does not allow stack to exceed 1024":
|
test "dup does not allow stack to exceed 1024":
|
||||||
var stack = newStack()
|
var stack = newStack()
|
||||||
stack.push(1.u256)
|
stack.push(1.u256)
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
# 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
|
|
||||||
unittest, stint, eth_common,
|
|
||||||
./test_helpers, ./fixtures,
|
|
||||||
../nimbus/[db/backends/memory_backend, db/state_db, chain, constants, utils/hexadecimal, vm_state],
|
|
||||||
../nimbus/[vm/base, computation]
|
|
||||||
|
|
||||||
import typetraits
|
|
||||||
|
|
||||||
suite "VM":
|
|
||||||
test "Apply transaction with no validation":
|
|
||||||
var
|
|
||||||
chain = chainWithoutBlockValidation()
|
|
||||||
vm = chain.getVM()
|
|
||||||
# txIdx = len(vm.`block`.transactions) # Can't take len of a runtime field
|
|
||||||
let
|
|
||||||
recipient = parseAddress("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0c")
|
|
||||||
amount = 100.u256
|
|
||||||
ethaddr_from = chain.fundedAddress
|
|
||||||
tx = newTransaction(vm, ethaddr_from, recipient, amount, chain.fundedAddressPrivateKey)
|
|
||||||
# (computation, _) = vm.applyTransaction(tx)
|
|
||||||
# accessLogs = computation.vmState.accessLogs
|
|
||||||
|
|
||||||
# check(not computation.isError)
|
|
||||||
|
|
||||||
let
|
|
||||||
# txGas = tx.gasPrice * constants.GAS_TX
|
|
||||||
state_db = vm.state.readOnlyStateDB
|
|
||||||
b = vm.`block`
|
|
||||||
|
|
||||||
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
|
|
|
@ -9,14 +9,12 @@ import
|
||||||
unittest, strformat, strutils, sequtils, tables, stint, json, ospaths, times,
|
unittest, strformat, strutils, sequtils, tables, stint, json, ospaths, times,
|
||||||
./test_helpers,
|
./test_helpers,
|
||||||
../nimbus/[constants, errors, logging],
|
../nimbus/[constants, errors, logging],
|
||||||
../nimbus/[chain, vm_state, computation, opcode, vm_types],
|
../nimbus/[vm_state, vm_types],
|
||||||
../nimbus/utils/[header, padding],
|
../nimbus/utils/[header, padding],
|
||||||
../nimbus/vm/[gas_meter, message, code_stream, stack],
|
../nimbus/vm/interpreter,
|
||||||
../nimbus/vm/forks/vm_forks, ../nimbus/db/[db_chain, state_db, backends/memory_backend],
|
../nimbus/db/[db_chain, state_db, backends/memory_backend],
|
||||||
eth_common
|
eth_common
|
||||||
|
|
||||||
from ../nimbus/opcode_table import OpLogic
|
|
||||||
|
|
||||||
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus)
|
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus)
|
||||||
|
|
||||||
suite "vm json tests":
|
suite "vm json tests":
|
||||||
|
@ -47,7 +45,7 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||||
let message = newMessage(
|
let message = newMessage(
|
||||||
to = fexec{"address"}.getStr.parseAddress,
|
to = fexec{"address"}.getStr.parseAddress,
|
||||||
sender = fexec{"caller"}.getStr.parseAddress,
|
sender = fexec{"caller"}.getStr.parseAddress,
|
||||||
value = fexec{"value"}.getHexadecimalInt.u256,
|
value = cast[uint](fexec{"value"}.getHexadecimalInt).u256, # Cast workaround for negative value
|
||||||
data = fexec{"data"}.getStr.mapIt(it.byte),
|
data = fexec{"data"}.getStr.mapIt(it.byte),
|
||||||
code = code,
|
code = code,
|
||||||
gas = fexec{"gas"}.getHexadecimalInt,
|
gas = fexec{"gas"}.getHexadecimalInt,
|
||||||
|
|
Loading…
Reference in New Issue