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

Add shard blob tx gas calculations #5596

Merged
merged 37 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6cd45c7
Add data gas calculations
flcl42 Apr 21, 2023
7886362
ChainSpecs/BlockProcessing: Fix syncing on Genesis block due to Exces…
spencer-tb May 4, 2023
2cd8bd7
TxValidator: Move KZG version check into network wrapper verification.
spencer-tb May 5, 2023
da546b4
ExcessData gas on genesis block
flcl42 May 9, 2023
1fa67f8
Check versioned hash earlier
flcl42 May 11, 2023
bd49c9d
Remake gas, preview
flcl42 Jun 1, 2023
a7120a8
Fix recursion
flcl42 Jun 3, 2023
6630c96
Add tests, refactor
flcl42 Jun 5, 2023
f363565
Get rid of parent block header finder
flcl42 Jun 5, 2023
2127d3b
Clean up
flcl42 Jun 5, 2023
4548a9f
Clean up checks
flcl42 Jun 5, 2023
d86ec23
Fix tests
flcl42 Jun 5, 2023
a132a10
Fix header mapping to rpc
flcl42 Jun 5, 2023
25b56af
Fix data gas calculations
flcl42 Jun 5, 2023
f0a5e4c
Add safety checks
flcl42 Jun 5, 2023
4fc22f1
Fix and improve
flcl42 Jun 5, 2023
3e6253d
Blob gas info in receipts (#5767)
deffrian Jun 6, 2023
14e9ce2
Increase data gas limits
flcl42 Jun 9, 2023
7c61b53
Clean up
flcl42 Jun 9, 2023
d41f110
Add more blob space
flcl42 Jun 12, 2023
d2b5311
Fix tests; clean up
flcl42 Jun 12, 2023
9913404
Add tests, refacator
flcl42 Jun 14, 2023
d093db7
Merge remote-tracking branch 'origin/master' into feature/eip-4844-ga…
flcl42 Jun 14, 2023
6105dfb
Fix MaxFeePerDataGas affects consensus on low balance
flcl42 Jun 14, 2023
da4d479
Improve max fee per data gas fix
flcl42 Jun 15, 2023
a681613
Fix receipts
flcl42 Jun 16, 2023
9f25cb6
Merge remote-tracking branch 'origin/master' into feature/eip-4844-ga…
flcl42 Jun 16, 2023
ec698ab
Merge remote-tracking branch 'origin/master' into feature/eip-4844-ga…
flcl42 Jun 19, 2023
8c2dc1d
Add overflow checks
flcl42 Jun 19, 2023
8a73222
Fix tests
flcl42 Jun 19, 2023
c307703
Fix encoding; improve text; clean up
flcl42 Jun 22, 2023
e7d3e4c
Merge remote-tracking branch 'origin/master' into feature/eip-4844-ga…
flcl42 Jun 22, 2023
06f9de5
Merge remote-tracking branch 'origin/master' into feature/eip-4844-ga…
flcl42 Jun 26, 2023
b7bc7b6
Merge remote-tracking branch 'origin/master' into feature/eip-4844-ga…
flcl42 Jun 29, 2023
f8fdd8d
Add gas fields to the local 4844 network genesis
flcl42 Jun 29, 2023
2a66fb5
Refactor BlockValidator
flcl42 Jun 30, 2023
fbdf0a9
Add additional check
flcl42 Jun 30, 2023
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
4 changes: 3 additions & 1 deletion src/Nethermind/Chains/eip4844_local.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
}
},
"timestamp": 0,
"baseFeePerGas": "0x7"
"baseFeePerGas": "0x7",
"dataGasUsed": "0x0",
"excessDataGas": "0x0"
},
"accounts": {
"0x8A04d14125D0FDCDc742F4A05C051De07232EDa4": {
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
header.MixHash = test.CurrentRandom;

Stopwatch stopwatch = Stopwatch.StartNew();
var txValidator = new TxValidator((MainnetSpecProvider.Instance.ChainId));
var spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber);
TxValidator? txValidator = new((MainnetSpecProvider.Instance.ChainId));
IReleaseSpec? spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber);
if (test.Transaction.ChainId == null)
test.Transaction.ChainId = MainnetSpecProvider.Instance.ChainId;
bool isValid = txValidator.IsWellFormed(test.Transaction, spec);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using FluentAssertions;
using Nethermind.Abi;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.Receipts;
using Nethermind.Consensus;
using Nethermind.Consensus.AuRa;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
using Nethermind.State;
using NSubstitute;
using NUnit.Framework;
using NUnit.Framework.Internal.Execution;

namespace Nethermind.Blockchain.Test.Producers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,26 +151,35 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases
{
get
{
ProperTransactionsSelectedTestCase maxTransactionsSelected = ProperTransactionsSelectedTestCase.Default;
ProperTransactionsSelectedTestCase maxTransactionsSelected = ProperTransactionsSelectedTestCase.Eip1559Default;
maxTransactionsSelected.ReleaseSpec = Cancun.Instance;
maxTransactionsSelected.BaseFee = 1;
maxTransactionsSelected.Transactions.ForEach(tx =>
{
tx.Type = TxType.Blob;
tx.BlobVersionedHashes = new byte[1][];
tx.MaxFeePerDataGas = 1;
});
maxTransactionsSelected.Transactions[1].BlobVersionedHashes =
new byte[Eip4844Constants.MaxBlobsPerBlock - 1][];
new byte[Eip4844Constants.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob - 1][];
maxTransactionsSelected.ExpectedSelectedTransactions.AddRange(
maxTransactionsSelected.Transactions.OrderBy(t => t.Nonce).Take(2));
yield return new TestCaseData(maxTransactionsSelected).SetName("Enough transactions selected");

ProperTransactionsSelectedTestCase enoughTransactionsSelected =
ProperTransactionsSelectedTestCase.Default;
ProperTransactionsSelectedTestCase.Eip1559Default;
enoughTransactionsSelected.ReleaseSpec = Cancun.Instance;
enoughTransactionsSelected.BaseFee = 1;

Transaction[] expectedSelectedTransactions =
enoughTransactionsSelected.Transactions.OrderBy(t => t.Nonce).ToArray();
expectedSelectedTransactions[0].Type = TxType.Blob;
expectedSelectedTransactions[0].BlobVersionedHashes = new byte[Eip4844Constants.MaxBlobsPerBlock][];
expectedSelectedTransactions[0].BlobVersionedHashes =
new byte[Eip4844Constants.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob][];
expectedSelectedTransactions[0].MaxFeePerDataGas = 1;
expectedSelectedTransactions[1].Type = TxType.Blob;
expectedSelectedTransactions[1].BlobVersionedHashes = new byte[1][];
expectedSelectedTransactions[1].MaxFeePerDataGas = 1;
enoughTransactionsSelected.ExpectedSelectedTransactions.AddRange(
expectedSelectedTransactions.Where((tx, index) => index != 1));
yield return new TestCaseData(enoughTransactionsSelected).SetName(
Expand Down Expand Up @@ -240,9 +249,13 @@ void SetAccountStates(IEnumerable<Address> missingAddresses)
TxPoolTxSource poolTxSource = new(transactionPool, specProvider,
transactionComparerProvider, LimboLogs.Instance, txFilterPipeline);


BlockHeaderBuilder parentHeader = Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).WithBaseFee(testCase.BaseFee);
if (spec.IsEip4844Enabled)
{
parentHeader = parentHeader.WithExcessDataGas(0);
}
IEnumerable<Transaction> selectedTransactions =
poolTxSource.GetTransactions(Build.A.BlockHeader.WithStateRoot(stateProvider.StateRoot).WithBaseFee(testCase.BaseFee).TestObject,
poolTxSource.GetTransactions(parentHeader.TestObject,
testCase.GasLimit);
selectedTransactions.Should()
.BeEquivalentTo(testCase.ExpectedSelectedTransactions, o => o.WithStrictOrdering());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,57 +1,105 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using System.Linq;
using Nethermind.Blockchain.Find;
using Nethermind.Consensus.Validators;
using Nethermind.Core;
using Nethermind.Core.Specs;
using Nethermind.Core.Test.Builders;
using Nethermind.Logging;
using Nethermind.Specs.Forks;
using Nethermind.Specs.Test;
using NSubstitute;
using NUnit.Framework;

namespace Nethermind.Blockchain.Test.Validators;

public class ShardBlobBlockValidatorTests
{
[Test]
public void Not_null_ExcessDataGas_is_invalid_pre_cancun()
[TestCaseSource(nameof(DataGasFieldsPerForkTestCases))]
public static bool Data_gas_fields_should_be_set(IReleaseSpec spec, ulong? dataGasUsed, ulong? excessDataGas)
{
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance));
BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance);
bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block
.WithWithdrawalsRoot(TestItem.KeccakA)
.WithWithdrawals(TestItem.WithdrawalA_1Eth)
.WithExcessDataGas(1).TestObject);
Assert.False(isValid);
}

[Test]
public void Null_ExcessDataGas_is_invalid_post_cancun()
{
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Cancun.Instance));
BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance);
bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec));
HeaderValidator headerValidator = new(Substitute.For<IBlockTree>(), Always.Valid, specProvider, TestLogManager.Instance);
BlockValidator blockValidator = new(Always.Valid, headerValidator, Always.Valid, specProvider, TestLogManager.Instance);
return blockValidator.ValidateSuggestedBlock(Build.A.Block
.WithDataGasUsed(dataGasUsed)
.WithExcessDataGas(excessDataGas)
.WithWithdrawalsRoot(TestItem.KeccakA)
.WithWithdrawals(TestItem.WithdrawalA_1Eth)
.WithParent(Build.A.BlockHeader.TestObject)
.TestObject);
Assert.False(isValid);
}

[TestCase(0, ExpectedResult = true)]
[TestCase(Eip4844Constants.MaxBlobsPerBlock - 1, ExpectedResult = true)]
[TestCase(Eip4844Constants.MaxBlobsPerBlock, ExpectedResult = true)]
[TestCase(Eip4844Constants.MaxBlobsPerBlock + 1, ExpectedResult = false)]
public bool Blobs_per_block_count_is_valid(int blobsCount)
[TestCase(0ul, ExpectedResult = true)]
[TestCase(Eip4844Constants.MaxDataGasPerBlock - Eip4844Constants.DataGasPerBlob, ExpectedResult = true)]
[TestCase(Eip4844Constants.MaxDataGasPerBlock, ExpectedResult = true)]
[TestCase(Eip4844Constants.MaxDataGasPerBlock + Eip4844Constants.DataGasPerBlob, ExpectedResult = false)]
public bool Blobs_per_block_count_is_valid(ulong dataGasUsed)
{
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Cancun.Instance));
BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance);
BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, TestLogManager.Instance);
return blockValidator.ValidateSuggestedBlock(
Build.A.Block
.WithWithdrawalsRoot(TestItem.KeccakA)
.WithWithdrawals(TestItem.WithdrawalA_1Eth)
.WithExcessDataGas(1)
.WithTransactions(Build.A.Transaction.WithBlobVersionedHashes(blobsCount).TestObject)
.WithDataGasUsed(dataGasUsed)
.WithExcessDataGas(0)
.WithTransactions(Enumerable.Range(0, (int)(dataGasUsed / Eip4844Constants.DataGasPerBlob))
.Select(i => Build.A.Transaction.WithType(TxType.Blob)
.WithMaxFeePerDataGas(ulong.MaxValue)
.WithBlobVersionedHashes(1).TestObject).ToArray())
.TestObject);
}

public static IEnumerable<TestCaseData> DataGasFieldsPerForkTestCases
{
get
{
yield return new TestCaseData(Shanghai.Instance, null, null)
{
TestName = "Data gas fields are not set pre-Cancun",
ExpectedResult = true
};
yield return new TestCaseData(Shanghai.Instance, 0ul, null)
{
TestName = "DataGasUsed is set pre-Cancun",
ExpectedResult = false
};
yield return new TestCaseData(Shanghai.Instance, null, 0ul)
{
TestName = "ExcessDataGas is set pre-Cancun",
ExpectedResult = false
};
yield return new TestCaseData(Shanghai.Instance, 0ul, 0ul)
{
TestName = "Data gas fields are set pre-Cancun",
ExpectedResult = false
};


yield return new TestCaseData(Cancun.Instance, null, null)
{
TestName = "Data gas fields are not set post-Cancun",
ExpectedResult = false
};
yield return new TestCaseData(Cancun.Instance, 0ul, null)
{
TestName = "Just DataGasUsed is set post-Cancun",
ExpectedResult = false
};
yield return new TestCaseData(Cancun.Instance, null, 0ul)
{
TestName = "Just ExcessDataGas is set post-Cancun",
ExpectedResult = false
};
yield return new TestCaseData(Cancun.Instance, 0ul, 0ul)
{
TestName = "Data gas fields are set post-Cancun",
ExpectedResult = true
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public void ShardBlobTransactions_should_have_destination_set()
.WithChainId(TestBlockchainIds.ChainId)
.SignedAndResolved().TestObject;

Transaction txtxWithTo = Build.A.Transaction
Transaction txWithTo = Build.A.Transaction
.WithType(TxType.Blob)
.WithTimestamp(ulong.MaxValue)
.WithTo(TestItem.AddressA)
Expand All @@ -347,7 +347,7 @@ public void ShardBlobTransactions_should_have_destination_set()
.SignedAndResolved().TestObject;

Assert.That(txValidator.IsWellFormed(txWithoutTo, Cancun.Instance), Is.False);
Assert.That(txValidator.IsWellFormed(txtxWithTo, Cancun.Instance));
Assert.That(txValidator.IsWellFormed(txWithTo, Cancun.Instance));
}

[Timeout(Timeout.MaxTestTime)]
Expand All @@ -371,7 +371,6 @@ public bool MaxFeePerDataGas_should_be_set_for_blob_tx_only(TxType txType, bool
return txValidator.IsWellFormed(tx, Cancun.Instance);
}


[TestCaseSource(nameof(BlobVersionedHashInvalidTestCases))]
[TestCaseSource(nameof(BlobVersionedHashValidTestCases))]
public bool BlobVersionedHash_should_be_correct(byte[] hash)
Expand Down Expand Up @@ -407,36 +406,41 @@ private static IEnumerable<TestCaseData> BlobVersionedHashInvalidTestCases
{
yield return new TestCaseData(null) { TestName = "Null hash", ExpectedResult = false };
yield return new TestCaseData(MakeArray(0)) { TestName = "Empty hash", ExpectedResult = false };
yield return new TestCaseData(MakeArray(1, 1, 0))
yield return new TestCaseData(MakeArray(1, 1))
{
TestName = "Correct version, incorrect length",
ExpectedResult = false
};
yield return new TestCaseData(MakeArray(31, 1, 0))
yield return new TestCaseData(MakeArray(31, 1))
{
TestName = "Correct version, incorrect length",
ExpectedResult = false
};
yield return new TestCaseData(MakeArray(33, 1, 0))
yield return new TestCaseData(MakeArray(33, 1))
{
TestName = "Correct version, incorrect length",
ExpectedResult = false
};
yield return new TestCaseData(MakeArray(32, 0, 0))
yield return new TestCaseData(MakeArray(32, 0))
{
TestName = "Incorrect version, correct length",
ExpectedResult = false
};
yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 - 1, 0))
yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 - 1))
{
TestName = "Incorrect version, correct length",
ExpectedResult = false
};
yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 + 1, 0))
yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 + 1))
{
TestName = "Incorrect version, correct length",
ExpectedResult = false
};
yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1))
{
TestName = "Correct version, correct length",
ExpectedResult = true
};
}
}

Expand Down Expand Up @@ -494,19 +498,19 @@ static TransactionBuilder<Transaction> MakeTestObject(int blobCount = 1) => Buil
TestName = "More than minimum BlobVersionedHashes",
ExpectedResult = true
};
yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxBlobsPerTransaction - 1)
yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob - 1))
.SignedAndResolved().TestObject)
{
TestName = "Less than maximum BlobVersionedHashes",
ExpectedResult = true
};
yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxBlobsPerTransaction)
yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob))
.SignedAndResolved().TestObject)
{
TestName = "Maximum BlobVersionedHashes",
ExpectedResult = true
};
yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxBlobsPerTransaction + 1)
yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1))
.SignedAndResolved().TestObject)
{
TestName = "Too many BlobVersionedHashes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
using Nethermind.Consensus.Rewards;
using Nethermind.Consensus.Transactions;
using Nethermind.Consensus.Validators;
using Nethermind.Consensus.Withdrawals;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
Expand All @@ -37,7 +36,6 @@
using Nethermind.Trie.Pruning;
using Nethermind.TxPool;
using NUnit.Framework;
using BlockTree = Nethermind.Blockchain.BlockTree;
using Nethermind.Config;

namespace Nethermind.Clique.Test
Expand Down Expand Up @@ -123,7 +121,9 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f
_genesis.Header.Hash = _genesis.Header.CalculateHash();
_genesis3Validators.Header.Hash = _genesis3Validators.Header.CalculateHash();

TransactionProcessor transactionProcessor = new(goerliSpecProvider, stateProvider, new VirtualMachine(blockhashProvider, specProvider, nodeLogManager), nodeLogManager);
TransactionProcessor transactionProcessor = new(goerliSpecProvider, stateProvider,
new VirtualMachine(blockhashProvider, specProvider, nodeLogManager),
nodeLogManager);
BlockProcessor blockProcessor = new(
goerliSpecProvider,
Always.Valid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
using Nethermind.Core.Specs;
using Nethermind.Evm;
using Nethermind.Int256;
using Nethermind.Logging;
using Nethermind.Specs;
using Nethermind.State;

namespace Nethermind.Consensus.Processing
Expand Down Expand Up @@ -92,9 +90,19 @@ private bool HasEnoughFounds(Transaction transaction, in UInt256 senderBalance,
return false;
}

if (eip1559Enabled && !transaction.IsServiceTransaction && senderBalance < (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + transaction.Value)
UInt256 maxFee = 0;

if (eip1559Enabled && !transaction.IsServiceTransaction && senderBalance < (maxFee = (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + transaction.Value))
{
e.Set(TxAction.Skip, $"{maxFee} is higher than sender balance ({senderBalance}), MaxFeePerGas: ({transaction.MaxFeePerGas}), GasLimit {transaction.GasLimit}");
return false;
}

if (releaseSpec.IsEip4844Enabled && !transaction.IsServiceTransaction && (
flcl42 marked this conversation as resolved.
Show resolved Hide resolved
!DataGasCalculator.TryCalculateDataGasPrice(block.Header, transaction, out UInt256 dataGasPrice) ||
senderBalance < (maxFee = (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + dataGasPrice + transaction.Value)))
flcl42 marked this conversation as resolved.
Show resolved Hide resolved
{
e.Set(TxAction.Skip, $"MaxFeePerGas ({transaction.MaxFeePerGas}) times GasLimit {transaction.GasLimit} is higher than sender balance ({senderBalance})");
e.Set(TxAction.Skip, $"{maxFee} is higher than sender balance ({senderBalance}), MaxFeePerGas: ({transaction.MaxFeePerGas}), GasLimit {transaction.GasLimit}, DataGasPrice: {dataGasPrice}");
return false;
}

Expand Down
Loading