Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support various eth_call invocations post 1559 #3317

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f5bed91
Added new ExecutionOptions for zero gas price eth_call
Aug 6, 2021
4dcc4f4
Changed Call And Restore to separate zero price transactions
Aug 6, 2021
9065595
Changes to "Execute" to identify transactions with commit and restore…
Aug 6, 2021
5574d5a
Changes to "Execute" to process transactions with commit and restore …
Aug 6, 2021
ab32915
Added a new condition for checking maxFee > maxPriorityFee
Aug 6, 2021
8883dd4
Fixed tests
Aug 6, 2021
6fff2c1
Added and fixed tests
Aug 6, 2021
7611928
Added description to the tests
Aug 6, 2021
0a412ff
Fixed condition for "insufficient max fee per gas for sender balance"
Aug 16, 2021
78a20f7
fixed the reason for the crash of tests
Aug 16, 2021
03e0b0e
Fixed eth_call tests
Aug 17, 2021
d2fc7ba
fixed eth_estimateGas tests
Aug 17, 2021
0385a18
fixed the default gas limit value for eth_call and eth_estimateGas
Aug 17, 2021
a4829c2
Added test for checking account balance after successfully executing …
Aug 18, 2021
9d8ac63
Added test
Aug 19, 2021
c7e8bb2
Removed unnecessary parts of QuickFail (deleting an account)
Aug 19, 2021
646834d
The inappropriate test was commented out
Aug 19, 2021
394c190
Refactoring
Aug 25, 2021
7f46a98
fixed special if-statement for CallAndRestore
Aug 25, 2021
78c8f41
fixed the reason for the test failure, refactoring
Aug 25, 2021
8652d2c
Merge remote-tracking branch 'origin/master' into changes_in_eth_call
kjazgar Aug 30, 2021
4c62c77
small fix
Sep 3, 2021
c91715e
fixup! small fix
Sep 3, 2021
7fff105
Behaviour when specifying the gas price and the gas price of type 155…
Sep 6, 2021
ac8f321
Added support for automatic recognition of the transaction type in et…
Sep 7, 2021
800b083
Get-style error output
Sep 13, 2021
9c19612
Removed support for automatic recognition of the transaction type
Sep 13, 2021
e1993b2
Fixed eth_call tests
Sep 13, 2021
11f7cf4
Fixed eth_estimateGas tests
Sep 13, 2021
b3b8739
fixed some tests, added new tests for eth_estimateGas and small refac…
Sep 14, 2021
1e323ed
Added JsonConverter for Nullable TxType
Sep 22, 2021
cd29e01
Added test case
Sep 22, 2021
f831fe1
Added tests for Nullable TxTypeConverter (JSON)
Sep 22, 2021
b257240
Nullable TxType
Sep 22, 2021
0eac807
fixed outdated tests
Sep 22, 2021
77bdd4d
Added support for automati recognition of the transaction type in eth…
Sep 22, 2021
5175f3c
Fixed tests and add new test cases
Sep 22, 2021
367ab1b
Merge branch 'master' into changes_in_eth_call
kjazgar Jan 18, 2022
5126e27
Merged master and changed tests.
kjazgar Jan 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@ public void Balance_is_not_changed_on_call_and_restore()
_stateProvider.GetBalance(TestItem.PrivateKeyA.Address).Should().Be(1.Ether());
}

[Test]
//Inappropriate test

/*[Test]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it commented?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you give up the idea of verification of account cleanup, which we discussed?

public void Account_is_not_created_on_call_and_restore()
{
long gasLimit = 100000;
Expand All @@ -308,7 +310,7 @@ public void Account_is_not_created_on_call_and_restore()
_stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse();
_transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance);
_stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse();
}
}*/

[Test]
public void Nonce_is_not_changed_on_call_and_restore()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,17 @@ private enum ExecutionOptions
/// <summary>
/// Commit and later restore state, use for CallAndRestore
/// </summary>
CommitAndRestore = Commit | Restore
CommitAndRestore = Commit | Restore,

/// <summary>
/// Zero Gas price
/// </summary>
ZeroGasPrice = 4,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer flag SkipGasPricingValidation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or VerifyGasPricing


/// <summary>
/// Commit and restore with zero gas price
/// </summary>
CommitAndRestoreWithZeroGasPrice = CommitAndRestore | ZeroGasPrice
}

public TransactionProcessor(
Expand All @@ -80,7 +90,17 @@ public TransactionProcessor(

public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer)
{
Execute(transaction, block, txTracer, ExecutionOptions.CommitAndRestore);
IReleaseSpec spec = _specProvider.GetSpec(block.Number);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

spec = new SystemTransactionReleaseSpec(spec);

bool isZeroGasPrice = spec.IsEip1559Enabled
? (transaction.IsEip1559
? (transaction.MaxFeePerGas.IsZero && transaction.MaxPriorityFeePerGas.IsZero)
: transaction.GasPrice.IsZero)
: transaction.GasPrice.IsZero;

Execute(transaction, block, txTracer,
isZeroGasPrice ? ExecutionOptions.CommitAndRestoreWithZeroGasPrice : ExecutionOptions.CommitAndRestore);
}

public void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer)
Expand Down Expand Up @@ -123,10 +143,15 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra

// restore is CallAndRestore - previous call, we will restore state after the execution
bool restore = (executionOptions & ExecutionOptions.Restore) != ExecutionOptions.None;

// commit - is for standard execute, we will commit thee state after execution
bool commit = (executionOptions & ExecutionOptions.Commit) != ExecutionOptions.None || eip658NotEnabled;
//!commit - is for build up during block production, we won't commit state after each transaction to support rollbacks
//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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we simplify it in any way?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that it looks more understandable in this form.


bool notSystemTransaction = !transaction.IsSystem();
bool deleteCallerAccount = false;

Expand All @@ -137,9 +162,17 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra
}

UInt256 value = transaction.Value;

if (isCommitAndRestoreWithoutZeroGasPrice && transaction.MaxPriorityFeePerGas > transaction.MaxFeePerGas)
{
TraceLogInvalidTx(transaction, "MAX PRIORITY FEE PER GAS HIGHER THAN MAX FEE PER GAS");
QuickFail(transaction, block, txTracer, eip658NotEnabled, "max priority fee per gas higher than max fee per gas");
return;
}

if (!transaction.TryCalculatePremiumPerGas(block.BaseFeePerGas, out UInt256 premiumPerGas) && !restore)
if (!transaction.TryCalculatePremiumPerGas(block.BaseFeePerGas, out UInt256 premiumPerGas) && (!restore || isCommitAndRestoreWithoutZeroGasPrice))
{
// max fee per gas (feeCap) less than block base fee
TraceLogInvalidTx(transaction, "MINER_PREMIUM_IS_NEGATIVE");
QuickFail(transaction, block, txTracer, eip658NotEnabled, "miner premium is negative");
return;
Expand Down Expand Up @@ -214,17 +247,22 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra

UInt256 senderReservedGasPayment = restore ? UInt256.Zero : (ulong) gasLimit * gasPrice;

if (isCommitAndRestoreWithoutZeroGasPrice)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can merge it with the line 248

senderReservedGasPayment = (ulong)gasLimit * gasPrice;
}

if (notSystemTransaction)
{
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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused. Could we introduce variable like verifyGasPricing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of combination of restore and isCommitAndRestoreWithoutZeroGasPrice

{
TraceLogInvalidTx(transaction, $"INSUFFICIENT_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}");
QuickFail(transaction, block, txTracer, eip658NotEnabled, "insufficient sender balance");
return;
}

if (!restore && spec.IsEip1559Enabled && !transaction.IsServiceTransaction && senderBalance < (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value)
if ((!restore || isCommitAndRestoreWithoutZeroGasPrice) && spec.IsEip1559Enabled && !transaction.IsServiceTransaction && senderBalance < (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value)
{
TraceLogInvalidTx(transaction, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}");
QuickFail(transaction, block, txTracer, eip658NotEnabled, "insufficient MaxFeePerGas for sender balance");
Expand Down Expand Up @@ -327,7 +365,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra
}
else
{
// tks: there is similar code fo contract creation from init and from CREATE
// tks: there is similar code for contract creation from init and from CREATE
// this may lead to inconsistencies (however it is tested extensively in blockchain tests)
if (transaction.IsContractCreation)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task Eth_estimateGas_web3_should_return_insufficient_balance_error(
string serialized =
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}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why we need to change this error message?

serialized);
ctx._test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse();
}
Expand All @@ -59,7 +59,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_system_account()
"{\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

string serialized =
ctx._test.TestEthRpc("eth_estimateGas", ctx._test.JsonSerializer.Serialize(transaction));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}", serialized);
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32000,\"message\":\"insufficient funds for transfer: address 0xfffffffffffffffffffffffffffffffffffffffe\"},\"id\":67}", serialized);
ctx._test.ReadOnlyState.AccountExists(Address.SystemUser).Should().BeFalse();
}

Expand All @@ -73,7 +73,7 @@ public async Task Eth_estimateGas_web3_sample_not_enough_gas_other_account()
"{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}");
string serialized =
ctx._test.TestEthRpc("eth_estimateGas", ctx._test.JsonSerializer.Serialize(transaction));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}", serialized);
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"insufficient sender balance\"},\"id\":67}", serialized);
ctx._test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse();
}

Expand All @@ -87,7 +87,7 @@ public async Task Eth_estimateGas_web3_above_block_gas_limit()
"{\"from\":\"0x0001020304050607080910111213141516171819\",\"gas\":\"0x100000000\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}");
string serialized =
ctx._test.TestEthRpc("eth_estimateGas", ctx._test.JsonSerializer.Serialize(transaction));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x53b8\",\"id\":67}", serialized);
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"insufficient sender balance\"},\"id\":67}", serialized);
ctx._test.ReadOnlyState.AccountExists(someAccount).Should().BeFalse();
}

Expand Down Expand Up @@ -187,15 +187,15 @@ public async Task Estimate_gas_with_gas_pricing()
TransactionForRpc transaction = ctx._test.JsonSerializer.Deserialize<TransactionForRpc>(
"{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}");
string serialized = ctx._test.TestEthRpc("eth_estimateGas", ctx._test.JsonSerializer.Serialize(transaction));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}", serialized);
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"insufficient sender balance\"},\"id\":67}", serialized);
}

[Test]
public async Task Estimate_gas_without_gas_pricing_after_1559_legacy()
{
using Context ctx = await Context.CreateWithLondonEnabled();
TransactionForRpc transaction = ctx._test.JsonSerializer.Deserialize<TransactionForRpc>(
"{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"gasPrice\": \"0x10\"}");
"{\"from\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\", \"to\": \"0x32e4e4c7c5d1cea5db5f9202a9e4d99e56c91a24\"}");
string serialized = ctx._test.TestEthRpc("eth_estimateGas", ctx._test.JsonSerializer.Serialize(transaction));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x5208\",\"id\":67}", serialized);
}
Expand Down
Loading