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
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,
".."/[chain_config, utils, rpc/hexstrings],
".."/[chain_config, rpc/hexstrings],
./call_common
type
@ -128,65 +128,6 @@ proc txCallEvm*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork:
shallowCopy(call.accessList, tx.accessList)
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 =
var call = CallParams(
vmState: vmState,

View File

@ -1,13 +1,15 @@
import
macrocache, strutils, sequtils, unittest2,
stew/byteutils, chronicles, eth/common,
macrocache, strutils, sequtils, unittest2, times,
stew/byteutils, chronicles, eth/[common, keys],
stew/shims/macros
import
options, json, os, eth/trie/[db, hexary],
options, eth/trie/[db, hexary],
../nimbus/db/[db_chain, accounts_cache],
../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
{.experimental: "dynamicBindSym".}
@ -178,8 +180,8 @@ proc parseGasUsed(gas: NimNode): GasInt =
proc generateVMProxy(boa: Assembler): NimNode =
let
vmProxy = genSym(nskProc, "vmProxy")
blockNumber = ident("blockNumber")
chainDB = ident("chainDB")
vmState = ident("vmState")
title = boa.title
body = newLitFixed(boa)
@ -187,34 +189,55 @@ proc generateVMProxy(boa: Assembler): NimNode =
test `title`:
proc `vmProxy`(): bool =
let boa = `body`
runVM(`blockNumber`, `chainDB`, boa)
runVM(`vmState`, `chainDB`, boa)
{.gcsafe.}:
check `vmProxy`()
when defined(macro_assembler_debug):
echo result.toStrLit.strVal
const
blockFile = "tests" / "fixtures" / "PersistBlockTests" / "block47205.json"
proc initDatabase*(networkId = MainNet): (BaseVMState, BaseChainDB) =
let db = newBaseChainDB(newMemoryDB(), false, networkId, networkParams(networkId))
initializeEmptyDb(db)
proc initDatabase*(): (Uint256, BaseChainDB) =
let
node = json.parseFile(blockFile)
blockNumber = UInt256.fromHex(node["blockNumber"].getStr())
memoryDB = newMemoryDB()
state = node["state"]
parent = getCanonicalHead(db)
coinbase = hexToByteArray[20]("bb7b8287f3f0a933474a79eae42cbca977791171")
timestamp = parent.timestamp + initDuration(seconds = 1)
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:
let key = hexToSeqByte(k)
let value = hexToSeqByte(v.getStr())
memoryDB.put(key, value)
(vmState, db)
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 =
var asmResult = asmCallEvm(blockNumber, chainDB, boa.code, boa.data, boa.fork)
vmState.mutateStateDB:
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:
error "different success value", expected=boa.success, actual=true
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
return false
var stateDB = asmResult.vmState.accountDb
var stateDB = vmState.accountDb
stateDB.persist()
var
storageRoot = stateDB.getStorageRoot(asmResult.contractAddress)
storageRoot = stateDB.getStorageRoot(codeAddress)
trie = initSecureHexaryTrie(chainDB.db, storageRoot)
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
return false
let logs = asmResult.vmState.logEntries
let logs = vmState.logEntries
if logs.len != boa.logs.len:
error "different logs len", expected=boa.logs.len, actual=logs.len
return false

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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