make macro_assembler to use the same testEvmCall

it also allow the macro_assembler to write more test
of CALL and CREATE family which previously not possible
This commit is contained in:
jangko 2021-10-14 15:00:02 +07:00
parent 71273f2f4c
commit d93a8bc4a1
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
8 changed files with 99 additions and 138 deletions

View File

@ -8,9 +8,9 @@
import import
eth/common/eth_types, stint, options, stew/byteutils, eth/common/eth_types, stint, options, stew/byteutils,
".."/[vm_types, vm_state, vm_internals, vm_gas_costs, forks], ".."/[vm_types, vm_state, vm_gas_costs, forks],
".."/[db/db_chain, db/accounts_cache, transaction], eth/trie/db, ".."/[db/db_chain, db/accounts_cache, transaction], eth/trie/db,
".."/[chain_config, utils, rpc/hexstrings], ".."/[chain_config, rpc/hexstrings],
./call_common ./call_common
type type
@ -128,65 +128,6 @@ proc txCallEvm*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork:
shallowCopy(call.accessList, tx.accessList) shallowCopy(call.accessList, tx.accessList)
return runComputation(call).gasUsed return runComputation(call).gasUsed
type
AsmResult* = object
isSuccess*: bool
gasUsed*: GasInt
output*: seq[byte]
stack*: Stack
memory*: Memory
vmState*: BaseVMState
contractAddress*: EthAddress
proc asmCallEvm*(blockNumber: Uint256, chainDB: BaseChainDB, code, data: seq[byte], fork: Fork): AsmResult =
let
parentNumber = blockNumber - 1
parent = chainDB.getBlockHeader(parentNumber)
header = chainDB.getBlockHeader(blockNumber)
headerHash = header.blockHash
body = chainDB.getBlockBody(headerHash)
vmState = newBaseVMState(parent.stateRoot, header, chainDB)
tx = body.transactions[0]
sender = transaction.getSender(tx)
gasLimit = 500000000
gasUsed = 0 #tx.payload.intrinsicGas.GasInt + gasFees[fork][GasTXCreate]
# This is an odd sort of test, where some fields are taken from
# `body.transactions[0]` but other fields (like `gasLimit`) are not. Also it
# creates the new contract using `code` like `CREATE`, but then executes the
# contract like it's `CALL`.
doAssert tx.contractCreation
let contractAddress = generateAddress(sender, vmState.readOnlyStateDB.getNonce(sender))
vmState.mutateStateDB:
db.setCode(contractAddress, code)
let callResult = runComputation(CallParams(
vmState: vmState,
forkOverride: some(fork),
gasPrice: tx.gasPrice,
gasLimit: gasLimit - gasUsed,
sender: sender,
to: contractAddress,
isCreate: false,
value: tx.value,
input: data,
noIntrinsic: true, # Don't charge intrinsic gas.
noAccessList: true, # Don't initialise EIP-2929 access list.
noGasCharge: true, # Don't charge sender account for gas.
noRefund: true # Don't apply gas refund/burn rule.
))
# Some of these are extra returned state, for testing, that a normal EVMC API
# computation doesn't return. We'll have to obtain them outside EVMC.
result.isSuccess = not callResult.isError
result.gasUsed = callResult.gasUsed
result.output = callResult.output
result.stack = callResult.stack
result.memory = callResult.memory
result.vmState = vmState
result.contractAddress = contractAddress
proc testCallEvm*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: Fork): CallResult = proc testCallEvm*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: Fork): CallResult =
var call = CallParams( var call = CallParams(
vmState: vmState, vmState: vmState,

View File

@ -1,13 +1,15 @@
import import
macrocache, strutils, sequtils, unittest2, macrocache, strutils, sequtils, unittest2, times,
stew/byteutils, chronicles, eth/common, stew/byteutils, chronicles, eth/[common, keys],
stew/shims/macros stew/shims/macros
import import
options, json, os, eth/trie/[db, hexary], options, eth/trie/[db, hexary],
../nimbus/db/[db_chain, accounts_cache], ../nimbus/db/[db_chain, accounts_cache],
../nimbus/vm_internals, ../nimbus/forks, ../nimbus/vm_internals, ../nimbus/forks,
../nimbus/transaction/call_evm ../nimbus/transaction/call_evm,
../nimbus/[transaction, chain_config, genesis, vm_types, vm_state],
../nimbus/utils/difficulty
export byteutils export byteutils
{.experimental: "dynamicBindSym".} {.experimental: "dynamicBindSym".}
@ -178,8 +180,8 @@ proc parseGasUsed(gas: NimNode): GasInt =
proc generateVMProxy(boa: Assembler): NimNode = proc generateVMProxy(boa: Assembler): NimNode =
let let
vmProxy = genSym(nskProc, "vmProxy") vmProxy = genSym(nskProc, "vmProxy")
blockNumber = ident("blockNumber")
chainDB = ident("chainDB") chainDB = ident("chainDB")
vmState = ident("vmState")
title = boa.title title = boa.title
body = newLitFixed(boa) body = newLitFixed(boa)
@ -187,34 +189,55 @@ proc generateVMProxy(boa: Assembler): NimNode =
test `title`: test `title`:
proc `vmProxy`(): bool = proc `vmProxy`(): bool =
let boa = `body` let boa = `body`
runVM(`blockNumber`, `chainDB`, boa) runVM(`vmState`, `chainDB`, boa)
{.gcsafe.}: {.gcsafe.}:
check `vmProxy`() check `vmProxy`()
when defined(macro_assembler_debug): when defined(macro_assembler_debug):
echo result.toStrLit.strVal echo result.toStrLit.strVal
const proc initDatabase*(networkId = MainNet): (BaseVMState, BaseChainDB) =
blockFile = "tests" / "fixtures" / "PersistBlockTests" / "block47205.json" let db = newBaseChainDB(newMemoryDB(), false, networkId, networkParams(networkId))
initializeEmptyDb(db)
proc initDatabase*(): (Uint256, BaseChainDB) =
let let
node = json.parseFile(blockFile) parent = getCanonicalHead(db)
blockNumber = UInt256.fromHex(node["blockNumber"].getStr()) coinbase = hexToByteArray[20]("bb7b8287f3f0a933474a79eae42cbca977791171")
memoryDB = newMemoryDB() timestamp = parent.timestamp + initDuration(seconds = 1)
state = node["state"] header = BlockHeader(
blockNumber: 1.u256,
stateRoot: parent.stateRoot,
parentHash: parent.blockHash,
coinbase: coinbase,
timestamp: timestamp,
difficulty: db.config.calcDifficulty(timestamp, parent),
gasLimit: 100_000
)
vmState = newBaseVMState(parent.stateRoot, header, db)
for k, v in state: (vmState, db)
let key = hexToSeqByte(k)
let value = hexToSeqByte(v.getStr())
memoryDB.put(key, value)
result = (blockNumber, newBaseChainDB(memoryDB, false)) proc runVM*(vmState: BaseVMState, chainDB: BaseChainDB, boa: Assembler): bool =
const codeAddress = hexToByteArray[20]("460121576cc7df020759730751f92bd62fd78dd6")
let privateKey = PrivateKey.fromHex("7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d")[]
proc runVM*(blockNumber: Uint256, chainDB: BaseChainDB, boa: Assembler): bool = vmState.mutateStateDB:
var asmResult = asmCallEvm(blockNumber, chainDB, boa.code, boa.data, boa.fork) db.setCode(codeAddress, boa.code)
db.setBalance(codeAddress, 1_000_000.u256)
if asmResult.isSuccess: let unsignedTx = Transaction(
txType: TxLegacy,
nonce: 0,
gasPrice: 1.GasInt,
gasLimit: 500_000_000.GasInt,
to: codeAddress.some,
value: 500.u256,
payload: boa.data
)
let tx = signTransaction(unsignedTx, privateKey, chainDB.config.chainId, false)
let asmResult = testCallEvm(tx, tx.getSender, vmState, boa.fork)
if not asmResult.isError:
if boa.success == false: if boa.success == false:
error "different success value", expected=boa.success, actual=true error "different success value", expected=boa.success, actual=true
return false return false
@ -253,11 +276,11 @@ proc runVM*(blockNumber: Uint256, chainDB: BaseChainDB, boa: Assembler): bool =
error "different memory value", idx=i, expected=mem, actual=actual error "different memory value", idx=i, expected=mem, actual=actual
return false return false
var stateDB = asmResult.vmState.accountDb var stateDB = vmState.accountDb
stateDB.persist() stateDB.persist()
var var
storageRoot = stateDB.getStorageRoot(asmResult.contractAddress) storageRoot = stateDB.getStorageRoot(codeAddress)
trie = initSecureHexaryTrie(chainDB.db, storageRoot) trie = initSecureHexaryTrie(chainDB.db, storageRoot)
for kv in boa.storage: for kv in boa.storage:
@ -271,7 +294,7 @@ proc runVM*(blockNumber: Uint256, chainDB: BaseChainDB, boa: Assembler): bool =
error "storage has different value", key=key, expected=val, actual=value error "storage has different value", key=key, expected=val, actual=value
return false return false
let logs = asmResult.vmState.logEntries let logs = vmState.logEntries
if logs.len != boa.logs.len: if logs.len != boa.logs.len:
error "different logs len", expected=boa.logs.len, actual=logs.len error "different logs len", expected=boa.logs.len, actual=logs.len
return false return false

View File

@ -2,8 +2,7 @@ import macro_assembler, unittest2
proc opArithMain*() = proc opArithMain*() =
suite "Arithmetic Opcodes": suite "Arithmetic Opcodes":
setup: let (vmState, chainDB) = initDatabase()
let (blockNumber, chainDB) = initDatabase()
assembler: assembler:
title: "ADD_1" title: "ADD_1"
@ -439,3 +438,6 @@ proc opArithMain*() =
PUSH1 "0x0F" PUSH1 "0x0F"
SIGNEXTEND SIGNEXTEND
stack: "0x000000000000000000000000000000003f9b347132d29b62d161117bca8c7307" stack: "0x000000000000000000000000000000003f9b347132d29b62d161117bca8c7307"
when isMainModule:
opArithMain()

View File

@ -2,8 +2,7 @@ import macro_assembler, unittest2
proc opBitMain*() = proc opBitMain*() =
suite "Bitwise Opcodes": suite "Bitwise Opcodes":
setup: let (vmState, chainDB) = initDatabase()
let (blockNumber, chainDB) = initDatabase()
assembler: # AND OP assembler: # AND OP
title: "AND_1" title: "AND_1"
@ -655,3 +654,7 @@ proc opBitMain*() =
PUSH1 "0x00" PUSH1 "0x00"
NOT NOT
stack: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" stack: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
when isMainModule:
opBitMain()

View File

@ -4,8 +4,7 @@ import
proc opCustomMain*() = proc opCustomMain*() =
suite "Custom Opcodes Test": suite "Custom Opcodes Test":
setup: let (vmState, chainDB) = initDatabase()
let (blockNumber, chainDB) = initDatabase()
assembler: # CALLDATASIZE OP assembler: # CALLDATASIZE OP
title: "CALLDATASIZE_1" title: "CALLDATASIZE_1"
@ -178,41 +177,41 @@ proc opCustomMain*() =
title: "ADDRESS_1" title: "ADDRESS_1"
code: code:
Address Address
stack: "0x000000000000000000000000c669eaad75042be84daaf9b461b0e868b9ac1871" stack: "0x000000000000000000000000460121576cc7df020759730751f92bd62fd78dd6"
assembler: # BALANCE OP assembler: # BALANCE OP
title: "BALANCE_1" title: "BALANCE_1"
code: code:
Address Address
Balance Balance
stack: "0x000000000000000000000000000000000000000000000000cff56a1b273a8000" stack: "0x00000000000000000000000000000000000000000000000000000000000f4434"
assembler: # EIP2929 BALANCE OP assembler: # EIP2929 BALANCE OP
title: "EIP2929 BALANCE_1" title: "EIP2929 BALANCE_1"
code: code:
Address Address
Balance Balance
stack: "0x000000000000000000000000000000000000000000000000cff56a1b273a8000" stack: "0x00000000000000000000000000000000000000000000000000000000000f4434"
fork: berlin fork: berlin
gasused: 2602 gasused: 102
assembler: # ORIGIN OP assembler: # ORIGIN OP
title: "ORIGIN_1" title: "ORIGIN_1"
code: code:
Origin Origin
stack: "0x000000000000000000000000fbe0afcd7658ba86be41922059dd879c192d4c73" stack: "0x0000000000000000000000008aeeda4d805471df9b2a5b0f38a0c3bcba786b"
assembler: # CALLER OP assembler: # CALLER OP
title: "CALLER_1" title: "CALLER_1"
code: code:
Caller Caller
stack: "0x000000000000000000000000fbe0afcd7658ba86be41922059dd879c192d4c73" stack: "0x0000000000000000000000008aeeda4d805471df9b2a5b0f38a0c3bcba786b"
assembler: # CALLVALUE OP assembler: # CALLVALUE OP
title: "CALLVALUE_1" title: "CALLVALUE_1"
code: code:
CallValue CallValue
stack: "0xcff56a1b273a8000" stack: "0x01f4"
assembler: # SHA3 OP assembler: # SHA3 OP
title: "SHA3_1" title: "SHA3_1"
@ -253,9 +252,9 @@ proc opCustomMain*() =
assembler: # BLOCKHASH OP assembler: # BLOCKHASH OP
title: "BLOCKHASH_1" title: "BLOCKHASH_1"
code: code:
Push2 "0xb864" # 47204, parent header number Push1 "0x00"
Blockhash Blockhash
stack: "0xa85842a20755232169db76c5bd4ad4672c1551fca4b07d0bd139cd0e6fef684d" stack: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
# current block coinbase/miner # current block coinbase/miner
assembler: # COINBASE OP assembler: # COINBASE OP
@ -269,42 +268,42 @@ proc opCustomMain*() =
title: "TIMESTAMP_1" title: "TIMESTAMP_1"
code: code:
TimeStamp TimeStamp
stack: "0x0000000000000000000000000000000000000000000000000000000055c46bba" stack: "0x0000000000000000000000000000000000000000000000000000000000000001"
# current block number # current block number
assembler: # NUMBER OP assembler: # NUMBER OP
title: "NUMBER_1" title: "NUMBER_1"
code: code:
Number Number
stack: "0x000000000000000000000000000000000000000000000000000000000000b865" stack: "0x0000000000000000000000000000000000000000000000000000000000000001"
# current difficulty # current difficulty
assembler: # DIFFICULTY OP assembler: # DIFFICULTY OP
title: "DIFFICULTY_1" title: "DIFFICULTY_1"
code: code:
Difficulty Difficulty
stack: "0x000000000000000000000000000000000000000000000000000001547c73822d" stack: "0x0000000000000000000000000000000000000000000000000000000400800000"
# ?? # tx gas price
assembler: # GASPRICE OP assembler: # GASPRICE OP
title: "GASPRICE_1" title: "GASPRICE_1"
code: code:
GasPrice GasPrice
stack: "0x000000000000000000000000000000000000000000000000000000746a528800" stack: "0x0000000000000000000000000000000000000000000000000000000000000001"
# ?? # gas remaining
assembler: # GAS OP assembler: # GAS OP
title: "GAS_1" title: "GAS_1"
code: code:
Gas Gas
stack: "0x000000000000000000000000000000000000000000000000000000001dcd64fe" stack: "0x000000000000000000000000000000000000000000000000000000001dcd64fe"
# ?? # block gas limit
assembler: # GASLIMIT OP assembler: # GASLIMIT OP
title: "GASLIMIT_1" title: "GASLIMIT_1"
code: code:
GasLimit GasLimit
stack: "0x000000000000000000000000000000000000000000000000000000000000a298" stack: "0x00000000000000000000000000000000000000000000000000000000000186a0"
assembler: # INVALID OP assembler: # INVALID OP
title: "INVALID_1" title: "INVALID_1"

View File

@ -1,12 +1,12 @@
import import
macro_assembler, unittest2, macros, macro_assembler, unittest2, macros,
stew/byteutils, eth/common, ../nimbus/db/state_db, stew/byteutils, eth/common,
../nimbus/db/db_chain ../nimbus/vm_state,
../nimbus/db/accounts_cache
proc opEnvMain*() = proc opEnvMain*() =
suite "Environmental Information Opcodes": suite "Environmental Information Opcodes":
setup: let (vmState, chainDB) = initDatabase()
let (blockNumber, chainDB) = initDatabase()
assembler: # CODECOPY OP assembler: # CODECOPY OP
title: "CODECOPY_1" title: "CODECOPY_1"
@ -178,22 +178,17 @@ proc opEnvMain*() =
"0x07" "0x07"
suite "Environmental Information Opcodes 2": suite "Environmental Information Opcodes 2":
setup: let
let (blockNumber, chainDB) = initDatabase() (vmState, chainDB) = initDatabase()
var acc: EthAddress acc = hexToByteArray[20]("0xfbe0afcd7658ba86be41922059dd879c192d4c73")
hexToByteArray("0xfbe0afcd7658ba86be41922059dd879c192d4c73", acc) code = hexToSeqByte("0x0102030405060708090A0B0C0D0E0F" &
var "611234600054615566602054603E6000602073471FD3AD3E9EEADEEC4608B92D" &
parent = chainDB.getBlockHeader(blockNumber - 1) "16CE6B500704CC3C6000605f556014600054601e60205463abcddcba6040545b" &
stateDB = newAccountStateDB(chainDB.db, parent.stateRoot, false) "51602001600a5254516040016014525451606001601e52545160800160285254" &
code = hexToSeqByte("0x0102030405060708090A0B0C0D0E0F" & "60a052546016604860003960166000f26000603f556103e756600054600053602002351234")
"611234600054615566602054603E6000602073471FD3AD3E9EEADEEC4608B92D" &
"16CE6B500704CC3C6000605f556014600054601e60205463abcddcba6040545b" &
"51602001600a5254516040016014525451606001601e52545160800160285254" &
"60a052546016604860003960166000f26000603f556103e756600054600053602002351234")
stateDB.setCode(acc, code) vmState.mutateStateDB:
parent.stateRoot = stateDB.rootHash db.setCode(acc, code)
chainDB.setHead(parent, true)
assembler: # EXTCODECOPY OP assembler: # EXTCODECOPY OP
title: "EXTCODECOPY_1" title: "EXTCODECOPY_1"

View File

@ -2,8 +2,7 @@ import macro_assembler, unittest2, macros, strutils
proc opMemoryMain*() = proc opMemoryMain*() =
suite "Memory Opcodes": suite "Memory Opcodes":
setup: let (vmState, chainDB) = initDatabase()
let (blockNumber, chainDB) = initDatabase()
assembler: # PUSH1 OP assembler: # PUSH1 OP
title: "PUSH1" title: "PUSH1"
@ -662,7 +661,7 @@ proc opMemoryMain*() =
code: code:
PUSH1 "0xAA" PUSH1 "0xAA"
SLOAD SLOAD
stack: "0x0000000000000000000000000000000000000000000000000000000000000000" stack: "0x0000000000000000000000000000000000000000000000000000000000000022"
assembler: # SLOAD OP assembler: # SLOAD OP
title: "SLOAD_2" title: "SLOAD_2"
@ -708,7 +707,7 @@ proc opMemoryMain*() =
SLOAD SLOAD
PC PC
stack: stack:
"0x00" "0x0000000000000000000000000000000000000000000000000000000000000022"
"0x0000000000000000000000000000000000000000000000000000000000000008" "0x0000000000000000000000000000000000000000000000000000000000000008"
memory: memory:
"0x00" "0x00"

View File

@ -4,8 +4,7 @@ import
proc opMiscMain*() = proc opMiscMain*() =
suite "Misc Opcodes": suite "Misc Opcodes":
setup: let (vmState, chainDB) = initDatabase()
let (blockNumber, chainDB) = initDatabase()
assembler: # LOG0 OP assembler: # LOG0 OP
title: "Log0" title: "Log0"
@ -20,7 +19,7 @@ proc opMiscMain*() =
"0x1234" "0x1234"
logs: logs:
( (
address: "0xc669eaad75042be84daaf9b461b0e868b9ac1871", address: "0x460121576cc7df020759730751f92bd62fd78dd6",
data: "0x0000000000000000000000000000000000000000000000000000000000001234" data: "0x0000000000000000000000000000000000000000000000000000000000001234"
) )
@ -38,7 +37,7 @@ proc opMiscMain*() =
"0x1234" "0x1234"
logs: logs:
( (
address: "0xc669eaad75042be84daaf9b461b0e868b9ac1871", address: "0x460121576cc7df020759730751f92bd62fd78dd6",
topics: ["0x9999"], topics: ["0x9999"],
data: "0x0000000000000000000000000000000000000000000000000000000000001234" data: "0x0000000000000000000000000000000000000000000000000000000000001234"
) )
@ -58,7 +57,7 @@ proc opMiscMain*() =
"0x1234" "0x1234"
logs: logs:
( (
address: "0xc669eaad75042be84daaf9b461b0e868b9ac1871", address: "0x460121576cc7df020759730751f92bd62fd78dd6",
topics: ["0x6666", "0x9999"], topics: ["0x6666", "0x9999"],
data: "0x0000000000000000000000000000000000000000000000000000000000001234" data: "0x0000000000000000000000000000000000000000000000000000000000001234"
) )
@ -79,7 +78,7 @@ proc opMiscMain*() =
"0x1234" "0x1234"
logs: logs:
( (
address: "0xc669eaad75042be84daaf9b461b0e868b9ac1871", address: "0x460121576cc7df020759730751f92bd62fd78dd6",
topics: ["0x3333", "0x6666", "0x9999"], topics: ["0x3333", "0x6666", "0x9999"],
data: "0x0000000000000000000000000000000000000000000000000000000000001234" data: "0x0000000000000000000000000000000000000000000000000000000000001234"
) )
@ -101,7 +100,7 @@ proc opMiscMain*() =
"0x1234" "0x1234"
logs: logs:
( (
address: "0xc669eaad75042be84daaf9b461b0e868b9ac1871", address: "0x460121576cc7df020759730751f92bd62fd78dd6",
topics: ["0x5555", "0x3333", "0x6666", "0x9999"], topics: ["0x5555", "0x3333", "0x6666", "0x9999"],
data: "0x0000000000000000000000000000000000000000000000000000000000001234" data: "0x0000000000000000000000000000000000000000000000000000000000001234"
) )