Support various eth_call invocations post 1559#3317
Support various eth_call invocations post 1559#3317MansurovB-source wants to merge 39 commits intomasterfrom
Conversation
… with zero gas price
…with zero gas price
| //we commit only after all block is constructed | ||
|
|
||
| // commitAndRestoreWithoutZeroGasPrice is CallAndRestore without a zero gas price | ||
| bool isCommitAndRestoreWithoutZeroGasPrice = commit && restore && ((executionOptions & ExecutionOptions.ZeroGasPrice) == ExecutionOptions.None); |
There was a problem hiding this comment.
Can we simplify it in any way?
There was a problem hiding this comment.
It seems to me that it looks more understandable in this form.
| [Test] | ||
| //Inappropriate test | ||
|
|
||
| /*[Test] |
There was a problem hiding this comment.
Did you give up the idea of verification of account cleanup, which we discussed?
| /// <summary> | ||
| /// Zero Gas price | ||
| /// </summary> | ||
| ZeroGasPrice = 4, |
There was a problem hiding this comment.
I would prefer flag SkipGasPricingValidation
| public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer) | ||
| { | ||
| Execute(transaction, block, txTracer, ExecutionOptions.CommitAndRestore); | ||
| IReleaseSpec spec = _specProvider.GetSpec(block.Number); |
There was a problem hiding this comment.
Take into account that you will change the behavior of three RPC calls here (eth_call, eth_estimateGas, and eth_createAccessList). Did you verify this behavior with other clients for each of the methods?
| UInt256 senderReservedGasPayment = restore ? UInt256.Zero : (ulong) gasLimit * gasPrice; | ||
|
|
||
| if (isCommitAndRestoreWithoutZeroGasPrice) | ||
| { |
There was a problem hiding this comment.
You can merge it with the line 248
| { | ||
| UInt256 senderBalance = _stateProvider.GetBalance(caller); | ||
| if (!restore && ((ulong) intrinsicGas * gasPrice + value > senderBalance || senderReservedGasPayment + value > senderBalance)) | ||
| if ((!restore || isCommitAndRestoreWithoutZeroGasPrice) && ((ulong) intrinsicGas * gasPrice + value > senderBalance || senderReservedGasPayment + value > senderBalance)) |
There was a problem hiding this comment.
I am confused. Could we introduce variable like verifyGasPricing?
There was a problem hiding this comment.
Instead of combination of restore and isCommitAndRestoreWithoutZeroGasPrice
| [ConfigItem( | ||
| Description = "Gas limit for eth_call and eth_estimateGas", | ||
| DefaultValue = "100000000")] | ||
| DefaultValue = "25000000")] |
There was a problem hiding this comment.
Could you explain why? Is it from eth_call spec?
There was a problem hiding this comment.
yes, it was in the specification
4.3.1.1 | eth_call MUST consider gas to equal 25 million if the gas parameter is equal to null[!]
There was a problem hiding this comment.
Ok, but you need to change it in JsonRpcConfig.cs too
# Conflicts: # src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs
| if (deleteCallerAccount) | ||
| { | ||
| _stateProvider.DeleteAccount(tx.SenderAddress ?? throw new InvalidOperationException()); | ||
| } |
There was a problem hiding this comment.
Maybe this should be put in a finally clause?
There was a problem hiding this comment.
private void QuickFail(Transaction tx, BlockHeader block, ITxTracer txTracer, bool eip658NotEnabled, string? reason, bool deleteCallerAccount = false)
{
try
{
block.GasUsed += tx.GasLimit;
Address recipient = tx.To ?? ContractAddress.From(
tx.SenderAddress ?? Address.Zero,
_stateProvider.GetNonce(tx.SenderAddress ?? Address.Zero));
if (txTracer.IsTracingReceipt)
{
Keccak? stateRoot = null;
if (eip658NotEnabled)
{
_stateProvider.RecalculateStateRoot();
stateRoot = _stateProvider.StateRoot;
}
txTracer.MarkAsFailed(recipient, tx.GasLimit, Array.Empty<byte>(), reason ?? "invalid", stateRoot);
}
}
finally
{
if (deleteCallerAccount)
{
_stateProvider.DeleteAccount(tx.SenderAddress ?? throw new InvalidOperationException());
}
}
}
Do something like this?
…h_call and the_estimateGas and small refactoring
| string serialized = ctx._test.TestEthRpc("eth_call", ctx._test.JsonSerializer.Serialize(transaction)); | ||
| Assert.AreEqual(2.Ether(), ctx._test.ReadOnlyState.GetBalance(new Address("0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24"))); | ||
| Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x\",\"id\":67}", serialized); | ||
|
|
There was a problem hiding this comment.
Cosmetic: remove whitespaces :)
| public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer) | ||
| { | ||
| Execute(transaction, block, txTracer, ExecutionOptions.CommitAndRestore); | ||
| bool skipGasPricing = _specProvider.GetSpec(block.Number).IsEip1559Enabled |
There was a problem hiding this comment.
Do other clients skip validation when we have GasPrice = 0 or when it is set to null in TransactionForRpc?
| ctx._test.TestEthRpc("eth_estimateGas", ctx._test.JsonSerializer.Serialize(transaction)); | ||
| Assert.AreEqual( | ||
| "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"insufficient funds for transfer: address 0x0001020304050607080910111213141516171819\"},\"id\":67}", | ||
| "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"insufficient sender balance\"},\"id\":67}", |
There was a problem hiding this comment.
Could you explain why we need to change this error message?
| @@ -58,7 +58,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_system_account() | |||
| "{\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}"); | |||
There was a problem hiding this comment.
It will be nice to add the same tests like it was before but with skipped gas pricing.
One more question: did geth change behavior only for blocks after 1559 or for all blocks?
| /// 5. After 1559: In geth if you do specify a gas price, that is interpreted as both the max and priority fee | ||
| /// and your account balance is checked against them + the current base fee. | ||
| /// </summary> | ||
| /// TODO maybe needs to be changed to ``geth`` |
There was a problem hiding this comment.
I think we should resolve this ToDo
| TransactionForRpc transaction = ctx._test.JsonSerializer.Deserialize<TransactionForRpc>( | ||
| "{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"maxFeePerGas\": \"0x2DA2830C\", \"value\": \"0x2DA2830C\"}"); | ||
| string serialized = ctx._test.TestEthRpc("eth_call", ctx._test.JsonSerializer.Serialize(transaction)); | ||
| Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32015,\"message\":\"VM execution error.\",\"data\":\"insufficient sender balance\"},\"id\":67}", serialized); |
There was a problem hiding this comment.
Could we return errors like in geth?
- max fee per gas less than block base fee
- max priority fee per gas higher than max fee per gas
| if ((transactionCall.MaxFeePerGas != null || transactionCall.MaxPriorityFeePerGas != null) && | ||
| transactionCall.GasPrice != null) | ||
| { | ||
| return ResultWrapper<TResult>.Fail("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified", ErrorCodes.InvalidInput); |
There was a problem hiding this comment.
It could be done in the next PRs, but please remember about other RPC methods like eth_sendTransaction (to verify in geth)
…_call and the_estimateGas and small refactoring
# Conflicts: # src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs # src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs # src/Nethermind/Nethermind.JsonRpc/JsonRpcConfig.cs
Fixes #4948
Changes:
Support various eth_call invocations post-1559
Types of changes
Testing
Requires testing
In case you checked yes, did you write tests??
#ethereum/go-ethereum#23027
#ethereum/execution-specs#35