RPC and GraphQL: Change `call` op to go through unified EVM runner
Simplify `call` to use `runComputation`; drop other code. The RPC/GraphQL `call` operation differs in many ways from regular transaction calls. The following flags are set, to disable various steps in processing. All four are true (disabling the corresponding step) for `call`: - `noIntrinsic`: Don't charge intrinsic gas. - `noAccessList`: Don't initialise EIP2929 access list. - `noGasCharge`: Don't charge sender account for gas. - `noRefund`: Don't apply gas refund/burn rule. Interestingly, the RPC/GraphQL `estimateGas` operation doesn't behave so differently from regular transactions. It might be that not all these steps should be disabled for `call` either. But until we investigate what RPC/GraphQL clients are expecting, keep the same behaviour as before. Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
parent
306c8e92c2
commit
b16aa2f1f7
|
@ -24,9 +24,9 @@ type
|
||||||
data*: seq[byte]
|
data*: seq[byte]
|
||||||
contractCreation*: bool
|
contractCreation*: bool
|
||||||
|
|
||||||
proc rpcSetupComputation(vmState: BaseVMState, rpc: RpcCallData,
|
proc rpcRunComputation(vmState: BaseVMState, rpc: RpcCallData,
|
||||||
gasLimit: GasInt, forkOverride = none(Fork)): Computation =
|
gasLimit: GasInt, forkOverride = none(Fork)): CallResult =
|
||||||
return setupComputation(CallParams(
|
return runComputation(CallParams(
|
||||||
vmState: vmState,
|
vmState: vmState,
|
||||||
forkOverride: forkOverride,
|
forkOverride: forkOverride,
|
||||||
gasPrice: rpc.gasPrice,
|
gasPrice: rpc.gasPrice,
|
||||||
|
@ -35,32 +35,32 @@ proc rpcSetupComputation(vmState: BaseVMState, rpc: RpcCallData,
|
||||||
to: rpc.to,
|
to: rpc.to,
|
||||||
isCreate: rpc.contractCreation,
|
isCreate: rpc.contractCreation,
|
||||||
value: rpc.value,
|
value: rpc.value,
|
||||||
input: rpc.data
|
input: rpc.data,
|
||||||
|
# This matches historical behaviour. It might be that not all these steps
|
||||||
|
# should be disabled for RPC/GraphQL `call`. But until we investigate what
|
||||||
|
# RPC/GraphQL clients are expecting, keep the same behaviour.
|
||||||
|
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.
|
||||||
))
|
))
|
||||||
|
|
||||||
proc rpcDoCall*(call: RpcCallData, header: BlockHeader, chain: BaseChainDB): HexDataStr =
|
proc rpcDoCall*(call: RpcCallData, header: BlockHeader, chain: BaseChainDB): HexDataStr =
|
||||||
# TODO: handle revert and error
|
# TODO: handle revert and error
|
||||||
# TODO: handle contract ABI
|
# TODO: handle contract ABI
|
||||||
var
|
# we use current header stateRoot, unlike block validation
|
||||||
# we use current header stateRoot, unlike block validation
|
# which use previous block stateRoot
|
||||||
# which use previous block stateRoot
|
# TODO: ^ Check it's correct to use current header stateRoot, not parent
|
||||||
vmState = newBaseVMState(header.stateRoot, header, chain)
|
let vmState = newBaseVMState(header.stateRoot, header, chain)
|
||||||
comp = rpcSetupComputation(vmState, call, call.gas)
|
let callResult = rpcRunComputation(vmState, call, call.gas)
|
||||||
|
return hexDataStr(callResult.output)
|
||||||
comp.execComputation()
|
|
||||||
result = hexDataStr(comp.output)
|
|
||||||
|
|
||||||
proc rpcMakeCall*(call: RpcCallData, header: BlockHeader, chain: BaseChainDB): (string, GasInt, bool) =
|
proc rpcMakeCall*(call: RpcCallData, header: BlockHeader, chain: BaseChainDB): (string, GasInt, bool) =
|
||||||
# TODO: handle revert
|
# TODO: handle revert
|
||||||
var
|
let parent = chain.getBlockHeader(header.parentHash)
|
||||||
parent = chain.getBlockHeader(header.parentHash)
|
let vmState = newBaseVMState(parent.stateRoot, header, chain)
|
||||||
vmState = newBaseVMState(parent.stateRoot, header, chain)
|
let callResult = rpcRunComputation(vmState, call, call.gas)
|
||||||
fork = toFork(chain.config, header.blockNumber)
|
return (callResult.output.toHex, callResult.gasUsed, callResult.isError)
|
||||||
comp = rpcSetupComputation(vmState, call, call.gas, some(fork))
|
|
||||||
|
|
||||||
let gas = comp.gasMeter.gasRemaining
|
|
||||||
comp.execComputation()
|
|
||||||
return (comp.output.toHex, gas - comp.gasMeter.gasRemaining, comp.isError)
|
|
||||||
|
|
||||||
func rpcIntrinsicGas(call: RpcCallData, fork: Fork): GasInt =
|
func rpcIntrinsicGas(call: RpcCallData, fork: Fork): GasInt =
|
||||||
var intrinsicGas = call.data.intrinsicGas(fork)
|
var intrinsicGas = call.data.intrinsicGas(fork)
|
||||||
|
|
Loading…
Reference in New Issue