From 76c4c72abb10244f351faa7883f94a08e13c8b63 Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Mon, 3 May 2021 10:04:15 +0100 Subject: [PATCH] RPC: Prepare rpcSetupComputation to support estimateGas The RPC `estimateGas` behaves differently from RPC `call` in a number of ways. These differences may be bugs due to `rpcEstimateGas` calling the EVM in a very different way than `rpcDoCall`, or they may be intentional. To be sure, we'll need to test behaviour with Geth, Infura etc to find out (their documentation isn't enough.) For now, though, we'll keep the same behaviour as we always had. `rpcEstimateGas` cannot use `rpcSetupComputation` as it is, because `estimateGas` accounts for "intrinsic gas", and `call` does not. This patch changes `rpcSetupComputation` to accomodate both behaviours. Signed-off-by: Jamie Lokier --- nimbus/transaction/call_evm.nim | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/nimbus/transaction/call_evm.nim b/nimbus/transaction/call_evm.nim index 3756f6aca..bf9a49187 100644 --- a/nimbus/transaction/call_evm.nim +++ b/nimbus/transaction/call_evm.nim @@ -8,7 +8,7 @@ import eth/common/eth_types, stint, options, stew/byteutils, - ".."/[vm_types, vm_types2, vm_state, vm_computation], + ".."/[vm_types, vm_types2, vm_state, vm_computation, utils], ".."/[db/db_chain, config, vm_state_transactions, rpc/hexstrings], ".."/[db/accounts_cache, p2p/executor], eth/trie/db @@ -22,23 +22,28 @@ type data*: seq[byte] contractCreation*: bool -proc rpcSetupComputation*(vmState: BaseVMState, call: RpcCallData, fork: Fork): Computation = +proc rpcSetupComputation*(vmState: BaseVMState, call: RpcCallData, + fork: Fork, gasLimit: GasInt): Computation = vmState.setupTxContext( origin = call.source, gasPrice = call.gasPrice, forkOverride = some(fork) ) - let msg = Message( - kind: evmcCall, + var msg = Message( + kind: if call.contractCreation: evmcCreate else: evmcCall, depth: 0, - gas: call.gas, + gas: gasLimit, sender: call.source, - contractAddress: call.to, + contractAddress: + if not call.contractCreation: + call.to + else: + generateAddress(call.source, vmState.readOnlyStateDB.getNonce(call.source)), codeAddress: call.to, value: call.value, data: call.data - ) + ) return newComputation(vmState, msg) @@ -50,7 +55,7 @@ proc rpcDoCall*(call: RpcCallData, header: BlockHeader, chain: BaseChainDB): Hex # which use previous block stateRoot vmState = newBaseVMState(header.stateRoot, header, chain) fork = toFork(chain.config, header.blockNumber) - comp = rpcSetupComputation(vmState, call, fork) + comp = rpcSetupComputation(vmState, call, fork, call.gas) comp.execComputation() result = hexDataStr(comp.output) @@ -62,7 +67,7 @@ proc rpcMakeCall*(call: RpcCallData, header: BlockHeader, chain: BaseChainDB): ( # which use previous block stateRoot vmState = newBaseVMState(header.stateRoot, header, chain) fork = toFork(chain.config, header.blockNumber) - comp = rpcSetupComputation(vmState, call, fork) + comp = rpcSetupComputation(vmState, call, fork, call.gas) let gas = comp.gasMeter.gasRemaining comp.execComputation()