From 6cd45c7a428c376ced46d4838e257a02d465f5e6 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Fri, 21 Apr 2023 20:59:39 +0300 Subject: [PATCH 01/31] Add data gas calculations --- .../Ethereum.Test.Base/BlockchainTestBase.cs | 4 +- .../Ethereum.Test.Base/GeneralTestBase.cs | 12 +- ...sts.TestAccountAbstractionRpcBlockchain.cs | 2 + .../BlockProcessorTests.cs | 4 + .../Producers/DevBlockproducerTests.cs | 2 + .../Nethermind.Blockchain.Test/ReorgTests.cs | 2 + .../TransactionSelectorTests.cs | 5 +- .../Validators/BlockValidatorTests.cs | 3 +- .../ShardBlobBlockValidatorTests.cs | 16 +- .../Validators/TxValidatorTests.cs | 7 +- .../Validators/WithdrawalValidatorTests.cs | 11 +- .../Nethermind.Blockchain/BlockTree.cs | 6 + .../Find/IBlockFinder.cs | 3 +- .../ReadOnlyBlockTree.cs | 7 + .../CliqueBlockProducerTests.cs | 10 +- .../AuRaBlockProcessor.cs | 1 + .../CliquePlugin.cs | 1 + .../NethDevPlugin.cs | 1 + .../Processing/BlockProcessor.cs | 13 ++ .../Processing/ReadOnlyChainProcessingEnv.cs | 3 + .../Processing/ReadOnlyTxProcessingEnv.cs | 2 +- .../Producers/BlockProducerBase.cs | 13 +- .../Producers/BlockProducerEnvFactory.cs | 2 + .../Producers/TxPoolTxSource.cs | 16 +- .../Validators/BlockValidator.cs | 32 +++- .../Validators/TxValidator.cs | 2 +- .../Blockchain/TestBlockchain.cs | 9 +- .../Builders/Build.BlockHeader.cs | 1 + .../Encoding/BlockDecoderTests.cs | 27 +++ .../Nethermind.Core.Test/NullBlockFinder.cs | 12 ++ src/Nethermind/Nethermind.Core/BlockHeader.cs | 4 +- .../Nethermind.Core/Eip4844Constants.cs | 7 +- .../Eip3198BaseFeeTests.cs | 5 +- .../Eip3529RefundsTests.cs | 9 +- .../Nethermind.Evm.Test/Eip3541Tests.cs | 2 +- .../IntrinsicGasCalculatorTests.cs | 60 ++++++- .../Tracing/GasEstimationTests.cs | 70 +++++--- .../TransactionProcessorFeeTests.cs | 3 +- .../TransactionProcessorTests.cs | 3 +- .../VirtualMachineTestsBase.cs | 18 +- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 165 +++++++++++------- .../IParentBlockHeaderFinder.cs | 11 ++ .../TransactionProcessor.cs | 16 +- .../Nethermind.Facade/BlockchainBridge.cs | 9 +- .../Nethermind.Facade/Eth/EthSyncingInfo.cs | 2 +- .../Proxy/Models/BlockModel.cs | 61 +++---- .../Steps/InitializeBlockchain.cs | 3 + .../EthModuleBenchmarks.cs | 2 +- .../Modules/Trace/ParityStyleTracerTests.cs | 3 +- .../Modules/TraceRpcModuleTests.cs | 1 + .../Modules/DebugModule/DebugModuleFactory.cs | 1 + .../Eth/EthModule.TransactionExecutor.cs | 2 +- .../Modules/Proof/ProofModuleFactory.cs | 2 +- .../Modules/Trace/TraceModuleFactory.cs | 1 + .../EngineModuleTests.Setup.cs | 2 + .../Nethermind.Merge.Plugin/MergePlugin.cs | 3 +- .../MevRpcModuleTests.TestMevRpcBlockchain.cs | 2 + .../Nethermind.Mev/Execution/TracerFactory.cs | 2 +- .../HeaderDecoder.cs | 1 - .../SyncServerTests.cs | 3 + .../SyncThreadTests.cs | 8 +- 61 files changed, 493 insertions(+), 217 deletions(-) create mode 100644 src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs create mode 100644 src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs diff --git a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs index 8e3e3a147db..7e17170981c 100644 --- a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs @@ -140,7 +140,7 @@ protected async Task RunTest(BlockchainTest test, Stopwatch? ITxValidator txValidator = new TxValidator(TestBlockchainIds.ChainId); IHeaderValidator headerValidator = new HeaderValidator(blockTree, Sealer, specProvider, _logManager); IUnclesValidator unclesValidator = new UnclesValidator(blockTree, headerValidator, _logManager); - IBlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, unclesValidator, specProvider, _logManager); + IBlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, unclesValidator, specProvider, blockTree, _logManager); IVirtualMachine virtualMachine = new VirtualMachine( blockhashProvider, specProvider, @@ -155,11 +155,13 @@ protected async Task RunTest(BlockchainTest test, Stopwatch? specProvider, stateProvider, virtualMachine, + blockTree, _logManager), stateProvider), stateProvider, receiptStorage, NullWitnessCollector.Instance, + blockTree, _logManager); IBlockchainProcessor blockchainProcessor = new BlockchainProcessor( diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index fc6382a4137..2708cca5357 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Nethermind.Blockchain; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -11,6 +12,7 @@ using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Db; +using Nethermind.Db.Blooms; using Nethermind.Int256; using Nethermind.Evm; using Nethermind.Evm.Tracing; @@ -20,6 +22,7 @@ using Nethermind.Specs.Forks; using Nethermind.Specs.Test; using Nethermind.State; +using Nethermind.State.Repositories; using Nethermind.Trie.Pruning; using NUnit.Framework; @@ -72,10 +75,15 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) specProvider, _logManager); + IDb blockInfoDb = new MemDb(); + IBlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, + new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, _logManager); + TransactionProcessor transactionProcessor = new( specProvider, stateProvider, virtualMachine, + blockTree, _logManager); InitializeTestState(test, stateProvider, specProvider); @@ -89,8 +97,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); diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs index 44f0aef692c..14306765660 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs @@ -192,6 +192,7 @@ protected override BlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, + BlockTree, LogManager); var parser = new AbiDefinitionParser(); @@ -281,6 +282,7 @@ private IBlockValidator CreateBlockValidator() headerValidator, Always.Valid, SpecProvider, + BlockTree, LogManager); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs index 58c6fb51a53..ad3a7d6da8c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs @@ -24,6 +24,7 @@ using System.Threading.Tasks; using System.Threading; using FluentAssertions; +using Nethermind.Blockchain.Find; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Withdrawals; @@ -51,6 +52,7 @@ public void Prepared_block_contains_author_field() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + Substitute.For(), LimboLogs.Instance); BlockHeader header = Build.A.BlockHeader.WithAuthor(TestItem.AddressD).TestObject; @@ -82,6 +84,7 @@ public void Can_store_a_witness() stateProvider, NullReceiptStorage.Instance, witnessCollector, + Substitute.For(), LimboLogs.Instance); BlockHeader header = Build.A.BlockHeader.WithAuthor(TestItem.AddressD).TestObject; @@ -111,6 +114,7 @@ public void Recovers_state_on_cancel() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + Substitute.For(), LimboLogs.Instance); BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithAuthor(TestItem.AddressD).TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs index c8de8362917..0be0241b6c9 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs @@ -67,6 +67,7 @@ public void Test() specProvider, stateProvider, virtualMachine, + blockTree, LimboLogs.Instance); BlockProcessor blockProcessor = new( specProvider, @@ -76,6 +77,7 @@ public void Test() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + blockTree, LimboLogs.Instance); BlockchainProcessor blockchainProcessor = new( blockTree, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index 8795add9d9c..abd3cdc5692 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -75,6 +75,7 @@ public void Setup() specProvider, stateProvider, virtualMachine, + _blockTree, LimboLogs.Instance); BlockProcessor blockProcessor = new( @@ -85,6 +86,7 @@ public void Setup() stateProvider, NullReceiptStorage.Instance, new WitnessCollector(memDbProvider.StateDb, LimboLogs.Instance), + _blockTree, LimboLogs.Instance); _blockchainProcessor = new BlockchainProcessor( _blockTree, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs index 66adabd5885..7609cfe8841 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs @@ -158,7 +158,7 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases tx.BlobVersionedHashes = new byte[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"); @@ -168,7 +168,8 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases 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[1].Type = TxType.Blob; expectedSelectedTransactions[1].BlobVersionedHashes = new byte[1][]; enoughTransactionsSelected.ExpectedSelectedTransactions.AddRange( diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs index 1993a8fce0f..ceb23dce925 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs @@ -4,6 +4,7 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Specs; @@ -23,7 +24,7 @@ public void When_more_uncles_than_allowed_returns_false() releaseSpec.MaximumUncleCount = 0; ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, releaseSpec)); - BlockValidator blockValidator = new(txValidator, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(txValidator, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); bool noiseRemoved = blockValidator.ValidateSuggestedBlock(Build.A.Block.TestObject); Assert.True(noiseRemoved); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs index 7518bf3303c..42bae6c1a2e 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs @@ -4,7 +4,9 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; +using Nethermind.Evm; using Nethermind.Logging; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -18,7 +20,7 @@ public class ShardBlobBlockValidatorTests public void Not_null_ExcessDataGas_is_invalid_pre_cancun() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) @@ -30,7 +32,7 @@ public void Not_null_ExcessDataGas_is_invalid_pre_cancun() 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); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) @@ -39,18 +41,18 @@ public void Null_ExcessDataGas_is_invalid_post_cancun() } [TestCase(0, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxBlobsPerBlock - 1, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxBlobsPerBlock, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxBlobsPerBlock + 1, ExpectedResult = false)] + [TestCase(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob - 1, ExpectedResult = true)] + [TestCase(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob, ExpectedResult = true)] + [TestCase(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1, ExpectedResult = false)] public bool Blobs_per_block_count_is_valid(int blobsCount) { 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, NullBlockFinder.Instance, LimboLogs.Instance); return blockValidator.ValidateSuggestedBlock( Build.A.Block .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) - .WithExcessDataGas(1) + .WithExcessDataGas(IntrinsicGasCalculator.CalculateExcessDataGas(0, blobsCount, specProvider.GenesisSpec)!.Value) .WithTransactions(Build.A.Transaction.WithBlobVersionedHashes(blobsCount).TestObject) .TestObject); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 2b63577924a..5aeaa1d09f3 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -327,7 +327,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) @@ -450,19 +449,19 @@ static TransactionBuilder 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(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(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob) .SignedAndResolved().TestObject) { TestName = "Maximum BlobVersionedHashes", ExpectedResult = true }; - yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxBlobsPerTransaction + 1) + yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1) .SignedAndResolved().TestObject) { TestName = "Too many BlobVersionedHashes", diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs index 97621db36b4..d3c69cba1b7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Specs.Forks; @@ -20,7 +21,7 @@ public class WithdrawalValidatorTests public void Not_null_withdrawals_are_invalid_pre_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, London.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(new Withdrawal[] { TestItem.WithdrawalA_1Eth, TestItem.WithdrawalB_2Eth }).TestObject); Assert.False(isValid); } @@ -29,7 +30,7 @@ public void Not_null_withdrawals_are_invalid_pre_shanghai() public void Null_withdrawals_are_invalid_post_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.TestObject); Assert.False(isValid); } @@ -38,7 +39,7 @@ public void Null_withdrawals_are_invalid_post_shanghai() public void Withdrawals_with_incorrect_withdrawals_root_are_invalid() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); Withdrawal[] withdrawals = { TestItem.WithdrawalA_1Eth, TestItem.WithdrawalB_2Eth }; Keccak withdrawalRoot = new WithdrawalTrie(withdrawals).RootHash; bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(withdrawals).WithWithdrawalsRoot(TestItem.KeccakD).TestObject); @@ -49,7 +50,7 @@ public void Withdrawals_with_incorrect_withdrawals_root_are_invalid() public void Empty_withdrawals_are_valid_post_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); Withdrawal[] withdrawals = { }; Keccak withdrawalRoot = new WithdrawalTrie(withdrawals).RootHash; bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(withdrawals).WithWithdrawalsRoot(withdrawalRoot).TestObject); @@ -60,7 +61,7 @@ public void Empty_withdrawals_are_valid_post_shanghai() public void Correct_withdrawals_block_post_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); Withdrawal[] withdrawals = { TestItem.WithdrawalA_1Eth, TestItem.WithdrawalB_2Eth }; Keccak withdrawalRoot = new WithdrawalTrie(withdrawals).RootHash; bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(withdrawals).WithWithdrawalsRoot(withdrawalRoot).TestObject); diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index e18069d1d65..419e00aebc0 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -24,6 +24,7 @@ using Nethermind.Serialization.Rlp; using Nethermind.State.Repositories; using Nethermind.Db.Blooms; +using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Blockchain { @@ -2031,5 +2032,10 @@ public void ForkChoiceUpdated(Keccak? finalizedBlockHash, Keccak? safeBlockHash) _metadataDb.Set(MetadataDbKeys.SafeBlockHash, Rlp.Encode(SafeHash!).Bytes); } } + + BlockHeader? IParentBlockHeaderFinder.FindParentHeader(BlockHeader block) => + this.FindParentHeader(block, + BlockTreeLookupOptions.TotalDifficultyNotNeeded | BlockTreeLookupOptions.DoNotCreateLevelIfMissing | + BlockTreeLookupOptions.AllowInvalid); } } diff --git a/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs b/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs index 9d31f61337c..09487f7b671 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs @@ -4,10 +4,11 @@ using System; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Blockchain.Find { - public interface IBlockFinder + public interface IBlockFinder : IParentBlockHeaderFinder { Keccak HeadHash { get; } diff --git a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs index 09a5478791a..1340fe5ce57 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs @@ -6,9 +6,11 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Visitors; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; namespace Nethermind.Blockchain @@ -199,5 +201,10 @@ IEnumerable GetPotentiallyCorruptedBlocks(long start) public void UpdateMainChain(IReadOnlyList blocks, bool wereProcessed, bool forceHeadBlock = false) => throw new InvalidOperationException($"{nameof(ReadOnlyBlockTree)} does not expect {nameof(UpdateMainChain)} calls"); public void ForkChoiceUpdated(Keccak? finalizedBlockHash, Keccak? safeBlockBlockHash) => throw new InvalidOperationException($"{nameof(ReadOnlyBlockTree)} does not expect {nameof(ForkChoiceUpdated)} calls"); + + BlockHeader? IParentBlockHeaderFinder.FindParentHeader(BlockHeader block) => + this.FindParentHeader(block, + BlockTreeLookupOptions.TotalDifficultyNotNeeded | BlockTreeLookupOptions.DoNotCreateLevelIfMissing | + BlockTreeLookupOptions.AllowInvalid); } } diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs index 1a8ab589711..225cb230d60 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs @@ -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; @@ -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 @@ -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), blockTree, + nodeLogManager); BlockProcessor blockProcessor = new( goerliSpecProvider, Always.Valid, @@ -132,6 +132,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + blockTree, nodeLogManager); BlockchainProcessor processor = new(blockTree, blockProcessor, new AuthorRecoveryStep(snapshotManager), stateReader, nodeLogManager, BlockchainProcessor.Options.NoReceipts); @@ -141,7 +142,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f WorldState minerStateProvider = new(minerTrieStore, codeDb, nodeLogManager); VirtualMachine minerVirtualMachine = new(blockhashProvider, specProvider, nodeLogManager); - TransactionProcessor minerTransactionProcessor = new(goerliSpecProvider, minerStateProvider, minerVirtualMachine, nodeLogManager); + TransactionProcessor minerTransactionProcessor = new(goerliSpecProvider, minerStateProvider, minerVirtualMachine, blockTree, nodeLogManager); BlockProcessor minerBlockProcessor = new( goerliSpecProvider, @@ -151,6 +152,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f minerStateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + blockTree, nodeLogManager); BlockchainProcessor minerProcessor = new(blockTree, minerBlockProcessor, new AuthorRecoveryStep(snapshotManager), stateReader, nodeLogManager, BlockchainProcessor.Options.NoReceipts); diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 52dc575fab0..90cd7643427 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -54,6 +54,7 @@ public AuRaBlockProcessor( stateProvider, receiptStorage, NullWitnessCollector.Instance, + blockTree, logManager, withdrawalProcessor) { diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs index 4180bd2a69a..57ccb6bb258 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs @@ -109,6 +109,7 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd producerEnv.StateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + getFromApi.BlockTree, getFromApi.LogManager, new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(producerEnv.StateProvider, getFromApi.LogManager))); diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs index 4db8a7d0aa6..87e2b7c6906 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs @@ -81,6 +81,7 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd producerEnv.StateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + getFromApi.BlockTree, getFromApi.LogManager); IBlockchainProcessor producerChainProcessor = new BlockchainProcessor( diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index dfdecd8f4d0..e961ff67ddc 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -3,8 +3,10 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; @@ -13,11 +15,13 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs.Forks; using Nethermind.State; +using Metrics = Nethermind.Blockchain.Metrics; namespace Nethermind.Consensus.Processing; @@ -28,6 +32,7 @@ public partial class BlockProcessor : IBlockProcessor protected readonly IWorldState _stateProvider; private readonly IReceiptStorage _receiptStorage; private readonly IWitnessCollector _witnessCollector; + private readonly IBlockFinder _blockFinder; private readonly IWithdrawalProcessor _withdrawalProcessor; private readonly IBlockValidator _blockValidator; private readonly IRewardCalculator _rewardCalculator; @@ -49,6 +54,7 @@ public BlockProcessor( IWorldState? stateProvider, IReceiptStorage? receiptStorage, IWitnessCollector? witnessCollector, + IBlockFinder? blockFinder, ILogManager? logManager, IWithdrawalProcessor? withdrawalProcessor = null) { @@ -58,6 +64,7 @@ public BlockProcessor( _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); _witnessCollector = witnessCollector ?? throw new ArgumentNullException(nameof(witnessCollector)); + _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _withdrawalProcessor = withdrawalProcessor ?? new WithdrawalProcessor(stateProvider, logManager); _rewardCalculator = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); _blockTransactionsExecutor = blockTransactionsExecutor ?? throw new ArgumentNullException(nameof(blockTransactionsExecutor)); @@ -231,6 +238,12 @@ protected virtual TxReceipt[] ProcessBlock( _stateProvider.Commit(spec); _stateProvider.RecalculateStateRoot(); + if (_specProvider.GetSpec(block.Header).IsEip4844Enabled) + { + block.Header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( + _blockFinder.FindParentHeader(block.Header)?.ExcessDataGas, + block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0), spec); + } block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = block.Header.CalculateHash(); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs index da38938699c..513951438d1 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; @@ -34,6 +35,7 @@ public ReadOnlyChainProcessingEnv( IReceiptStorage receiptStorage, IReadOnlyDbProvider dbProvider, ISpecProvider specProvider, + IBlockFinder blockFinder, ILogManager logManager, IBlockProcessor.IBlockTransactionsExecutor? blockTransactionsExecutor = null) { @@ -50,6 +52,7 @@ public ReadOnlyChainProcessingEnv( StateProvider, receiptStorage, NullWitnessCollector.Instance, + blockFinder, logManager); _blockProcessingQueue = new BlockchainProcessor(_txEnv.BlockTree, BlockProcessor, recoveryStep, _txEnv.StateReader, logManager, BlockchainProcessor.Options.NoReceipts); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index f99c5f01b12..9b8b1748e65 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -56,7 +56,7 @@ public ReadOnlyTxProcessingEnv( BlockhashProvider = new BlockhashProvider(BlockTree, logManager); Machine = new VirtualMachine(BlockhashProvider, specProvider, logManager); - TransactionProcessor = new TransactionProcessor(specProvider, StateProvider, Machine, logManager); + TransactionProcessor = new TransactionProcessor(specProvider, StateProvider, Machine, BlockTree, logManager); } public IReadOnlyTransactionProcessor Build(Keccak stateRoot) => new ReadOnlyTransactionProcessor(TransactionProcessor, StateProvider, stateRoot); diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index f3f54fb7849..4d2033798db 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -14,6 +15,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Int256; using Nethermind.Logging; @@ -44,7 +46,7 @@ public abstract class BlockProducerBase : IBlockProducer private IWorldState StateProvider { get; } private readonly IGasLimitCalculator _gasLimitCalculator; private readonly IDifficultyCalculator _difficultyCalculator; - private readonly ISpecProvider _specProvider; + protected readonly ISpecProvider _specProvider; private readonly ITxSource _txSource; private readonly IBlockProductionTrigger _trigger; private bool _isRunning; @@ -292,7 +294,7 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, _blocksConfig.GetExtraDataBytes()) { Author = blockAuthor, - MixHash = payloadAttributes?.PrevRandao + MixHash = payloadAttributes?.PrevRandao, }; UInt256 difficulty = _difficultyCalculator.Calculate(header, parent); @@ -301,6 +303,7 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, if (Logger.IsDebug) Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}."); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); + return header; } @@ -310,12 +313,6 @@ protected virtual Block PrepareBlock(BlockHeader parent, PayloadAttributes? payl IEnumerable transactions = GetTransactions(parent); - if (_specProvider.GetSpec(header).IsEip4844Enabled) - { - // TODO: Calculate ExcessDataGas depending on parent ExcessDataGas and number of blobs in txs - header.ExcessDataGas = 0; - } - return new BlockToProduce(header, transactions, Array.Empty(), payloadAttributes?.Withdrawals); } } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index 3d88b53ba6a..d6bb5a54a0c 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Config; using Nethermind.Consensus.Comparers; @@ -148,6 +149,7 @@ protected virtual BlockProcessor CreateBlockProcessor(ReadOnlyTxProcessingEnv re readOnlyTxProcessingEnv.StateProvider, receiptStorage, NullWitnessCollector.Instance, + _blockTree, logManager, new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(readOnlyTxProcessingEnv.StateProvider, logManager))); diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index adaccb99e94..f27869ad6c0 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Collections; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.TxPool; @@ -60,6 +61,8 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi // TODO: removing transactions from TX pool here seems to be a bad practice since they will // not come back if the block is ignored? int blobsCounter = 0; + UInt256? dataGasPrice = null; + foreach (Transaction tx in transactions) { i++; @@ -74,10 +77,18 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi bool success = _txFilterPipeline.Execute(tx, parent); if (!success) continue; - if (tx.Type == TxType.Blob) + if (tx.SupportsBlobs) { + dataGasPrice ??= IntrinsicGasCalculator.GetDataGasPrice(parent.ExcessDataGas.GetValueOrDefault()); int txAmountOfBlobs = tx.BlobVersionedHashes?.Length ?? 0; - if ((blobsCounter + txAmountOfBlobs) > Eip4844Constants.MaxBlobsPerBlock) + if (dataGasPrice > tx.MaxFeePerDataGas) + { + if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, data gas fee is too low."); + continue; + } + + if (IntrinsicGasCalculator.CalculateDataGas(blobsCounter + txAmountOfBlobs) > + Eip4844Constants.MaxDataGasPerBlock) { if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, no more blob space."); continue; @@ -97,7 +108,6 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi } if (_logger.IsDebug) _logger.Debug($"Potentially selected {selectedTransactions} out of {i} pending transactions checked."); - } protected virtual IEnumerable GetOrderedTransactions(IDictionary pendingTransactions, IComparer comparer) => diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 82858e12c3f..bfae38e4676 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -4,9 +4,12 @@ using System; using System.Linq; using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm; +using Nethermind.Int256; using Nethermind.Logging; using Nethermind.State.Proofs; using Nethermind.TxPool; @@ -19,6 +22,7 @@ public class BlockValidator : IBlockValidator private readonly ITxValidator _txValidator; private readonly IUnclesValidator _unclesValidator; private readonly ISpecProvider _specProvider; + private readonly IBlockFinder _blockFinder; private readonly ILogger _logger; public BlockValidator( @@ -26,12 +30,14 @@ public BlockValidator( IHeaderValidator? headerValidator, IUnclesValidator? unclesValidator, ISpecProvider? specProvider, + IBlockFinder? blockFinder, ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _txValidator = txValidator ?? throw new ArgumentNullException(nameof(txValidator)); _unclesValidator = unclesValidator ?? throw new ArgumentNullException(nameof(unclesValidator)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); + _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _headerValidator = headerValidator ?? throw new ArgumentNullException(nameof(headerValidator)); } @@ -100,7 +106,7 @@ public bool ValidateSuggestedBlock(Block block) if (!ValidateWithdrawals(block, spec, out _)) return false; - if (!ValidateBlobs(block, spec, out _)) + if (!ValidateBlobsAndExcessDataGas(block, spec, out _)) return false; return true; @@ -142,6 +148,11 @@ public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, B if (_logger.IsError) _logger.Error($"- state root: expected {suggestedBlock.Header.StateRoot}, got {processedBlock.Header.StateRoot}"); } + if (processedBlock.Header.ExcessDataGas != suggestedBlock.Header.ExcessDataGas) + { + if (_logger.IsError) _logger.Error($"- excess data gas: expected {suggestedBlock.Header.ExcessDataGas}, got {processedBlock.Header.ExcessDataGas}"); + } + for (int i = 0; i < processedBlock.Transactions.Length; i++) { if (receipts[i].Error is not null && receipts[i].GasUsed == 0 && receipts[i].Error == "invalid") @@ -193,7 +204,7 @@ private bool ValidateWithdrawals(Block block, IReleaseSpec spec, out string? err return true; } - private bool ValidateBlobs(Block block, IReleaseSpec spec, out string? error) + private bool ValidateBlobsAndExcessDataGas(Block block, IReleaseSpec spec, out string? error) { if (spec.IsEip4844Enabled && block.ExcessDataGas is null) { @@ -209,19 +220,30 @@ private bool ValidateBlobs(Block block, IReleaseSpec spec, out string? error) return false; } - int? blobsInBlock = 0; + int blobsInBlock = 0; for (int txIndex = block.Transactions.Length - 1; txIndex >= 0; txIndex--) { blobsInBlock += block.Transactions[txIndex].BlobVersionedHashes?.Length ?? 0; } - if (spec.IsEip4844Enabled && blobsInBlock > Eip4844Constants.MaxBlobsPerBlock) + if (IntrinsicGasCalculator.CalculateDataGas(blobsInBlock) > Eip4844Constants.MaxDataGasPerBlock) { - error = $"A block cannot contain more than {Eip4844Constants.MaxBlobsPerBlock} blobs."; + error = $"A block cannot have more than {Eip4844Constants.MaxDataGasPerBlock} data gas."; if (_logger.IsWarn) _logger.Warn(error); return false; } + UInt256? expectedExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( + (block.ParentHash is null ? null : _blockFinder.FindParentHeader(block.Header, BlockTreeLookupOptions.All)) + ?.ExcessDataGas, + blobsInBlock, spec); + + if (block.ExcessDataGas != expectedExcessDataGas) + { + error = $"ExcessDataGas field is incorrect: {block.ExcessDataGas}, should be {expectedExcessDataGas}."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } error = null; return true; } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index 14904972294..923586c9dac 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -119,7 +119,7 @@ transaction.BlobVersionedHashes is null && if (transaction.To is null || transaction.MaxFeePerDataGas is null || transaction.BlobVersionedHashes is null || - transaction.BlobVersionedHashes!.Length > Eip4844Constants.MaxBlobsPerTransaction || + IntrinsicGasCalculator.CalculateDataGas(transaction.BlobVersionedHashes!.Length) > Eip4844Constants.MaxDataGasPerTransaction || transaction.BlobVersionedHashes!.Length < Eip4844Constants.MinBlobsPerTransaction) { return false; diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 28ab3ba80fa..c9fa5e28fb2 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -149,7 +149,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = ReceiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new(new BlockhashProvider(BlockTree, LogManager), SpecProvider, LogManager); - TxProcessor = new TransactionProcessor(SpecProvider, State, virtualMachine, LogManager); + TxProcessor = new TransactionProcessor(SpecProvider, State, virtualMachine, BlockTree, LogManager); BlockPreprocessorStep = new RecoverSignatures(EthereumEcdsa, TxPool, SpecProvider, LogManager); HeaderValidator = new HeaderValidator(BlockTree, Always.Valid, SpecProvider, LogManager); @@ -160,6 +160,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = HeaderValidator, Always.Valid, SpecProvider, + BlockTree, LogManager); PoSSwitcher = NoPoS.Instance; @@ -298,6 +299,11 @@ protected virtual Block GetGenesisBlock() genesisBlockBuilder.WithAura(0, new byte[65]); } + if (SpecProvider.GenesisSpec.IsEip4844Enabled) + { + genesisBlockBuilder.WithExcessDataGas(0); + } + return genesisBlockBuilder.TestObject; } @@ -317,6 +323,7 @@ protected virtual IBlockProcessor CreateBlockProcessor() => State, ReceiptStorage, NullWitnessCollector.Instance, + BlockTree, LogManager); public async Task WaitForNewHead() diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/Build.BlockHeader.cs b/src/Nethermind/Nethermind.Core.Test/Builders/Build.BlockHeader.cs index 09204ba42a9..2a272f2296c 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/Build.BlockHeader.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/Build.BlockHeader.cs @@ -6,5 +6,6 @@ namespace Nethermind.Core.Test.Builders public partial class Build { public BlockHeaderBuilder BlockHeader => new(); + public BlockHeader EmptyBlockHeader => BlockHeader.TestObject; } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs index ed2e3f3fb23..0bccc8b6b12 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs @@ -56,6 +56,33 @@ public BlockDecoderTests() .WithUncles(uncles) .WithWithdrawals(8) .WithMixHash(Keccak.EmptyTreeHash) + .TestObject, + Build.A.Block + .WithNumber(1) + .WithBaseFeePerGas(1) + .WithTransactions(transactions) + .WithUncles(uncles) + .WithWithdrawals(8) + .WithExcessDataGas(0) + .WithMixHash(Keccak.EmptyTreeHash) + .TestObject, + Build.A.Block + .WithNumber(1) + .WithBaseFeePerGas(1) + .WithTransactions(transactions) + .WithUncles(uncles) + .WithWithdrawals(8) + .WithExcessDataGas(0xff) + .WithMixHash(Keccak.EmptyTreeHash) + .TestObject, + Build.A.Block + .WithNumber(1) + .WithBaseFeePerGas(1) + .WithTransactions(transactions) + .WithUncles(uncles) + .WithWithdrawals(8) + .WithExcessDataGas(UInt256.MaxValue) + .WithMixHash(Keccak.EmptyTreeHash) .TestObject }; } diff --git a/src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs b/src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs new file mode 100644 index 00000000000..c6de442298e --- /dev/null +++ b/src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain.Find; +using NSubstitute; + +namespace Nethermind.Core.Test; + +public static class NullBlockFinder +{ + public static IBlockFinder Instance = Substitute.For(); +} diff --git a/src/Nethermind/Nethermind.Core/BlockHeader.cs b/src/Nethermind/Nethermind.Core/BlockHeader.cs index 5c0bbcfd529..c85150f9274 100644 --- a/src/Nethermind/Nethermind.Core/BlockHeader.cs +++ b/src/Nethermind/Nethermind.Core/BlockHeader.cs @@ -68,8 +68,8 @@ public BlockHeader( public UInt256? ExcessDataGas { get; set; } public bool HasBody => (TxRoot is not null && TxRoot != Keccak.EmptyTreeHash) - || (UnclesHash is not null && UnclesHash != Keccak.OfAnEmptySequenceRlp) - || (WithdrawalsRoot is not null && WithdrawalsRoot != Keccak.EmptyTreeHash); + || (UnclesHash is not null && UnclesHash != Keccak.OfAnEmptySequenceRlp) + || (WithdrawalsRoot is not null && WithdrawalsRoot != Keccak.EmptyTreeHash); public bool HasTransactions => (TxRoot is not null && TxRoot != Keccak.EmptyTreeHash); diff --git a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs index 4ef6c219633..84da26216e1 100644 --- a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs @@ -8,7 +8,10 @@ namespace Nethermind.Core; public class Eip4844Constants { - public const int MaxBlobsPerBlock = 4; - public const int MaxBlobsPerTransaction = MaxBlobsPerBlock; public const int MinBlobsPerTransaction = 1; + + public const int DataGasPerBlob = 1 << 17; + public const int TargetDataGasPerBlock = 1 << 18; + public const int MaxDataGasPerBlock = 1 << 19; + public const int MaxDataGasPerTransaction = MaxDataGasPerBlock; } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs index 218f7a27a55..c787a8d031e 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs @@ -4,13 +4,12 @@ using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; -using Nethermind.Specs.Forks; -using NSubstitute; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -30,7 +29,7 @@ public class Eip3198BaseFeeTests : VirtualMachineTestsBase [TestCase(false, 0, false)] public void Base_fee_opcode_should_return_expected_results(bool eip3198Enabled, int baseFee, bool send1559Tx) { - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, NullBlockFinder.Instance, LimboLogs.Instance); byte[] code = Prepare.EvmCode .Op(Instruction.BASEFEE) .PushData(0) diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs index 80aa0346126..bde2edc9816 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs @@ -2,22 +2,15 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using FluentAssertions; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; -using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; -using Nethermind.Evm.Tracing; -using Nethermind.Evm.Tracing.GethStyle; using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; -using Nethermind.Serialization.Json; using Nethermind.Specs; using Nethermind.Specs.Forks; -using NSubstitute; using NUnit.Framework; namespace Nethermind.Evm.Test @@ -80,7 +73,7 @@ private void Test(string codeHex, long gasUsed, long refund, byte originalValue, TestState.CreateAccount(Recipient, 1.Ether()); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); TestState.Commit(eip3529Enabled ? London.Instance : Berlin.Instance); - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, BlockFinder, LimboLogs.Instance); long blockNumber = eip3529Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, Bytes.FromHexString(codeHex)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs index bef8582a4be..bf0adb8c348 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs @@ -100,7 +100,7 @@ void DeployCodeAndAssertTx(string code, bool eip3541Enabled, ContractDeployment break; } - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, BlockFinder, LimboLogs.Instance); long blockNumber = eip3541Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, createContract); diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index 64bfc890bba..02717cc9f70 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.Collections.Immutable; using System.IO; using FluentAssertions; using Nethermind.Core; @@ -41,7 +40,6 @@ public class IntrinsicGasCalculatorTests yield return (new byte[] { 1, 1, 0 }, 140, 36); yield return (new byte[] { 0, 0, 1, 1 }, 144, 40); } - [TestCaseSource(nameof(TestCaseSource))] public void Intrinsic_cost_is_calculated_properly((Transaction Tx, long Cost, string Description) testCase) { @@ -113,6 +111,64 @@ void Test(IReleaseSpec spec, bool isAfterRepricing) Test(Istanbul.Instance, true); Test(MuirGlacier.Instance, true); Test(Berlin.Instance, true); + Test(GrayGlacier.Instance, true); + Test(Shanghai.Instance, true); + Test(Cancun.Instance, true); + } + + public static IEnumerable<(UInt256 parentExcessDataGas, int newBlobsCount, UInt256 expectedCost)> ExcessDataGasTestCaseSource() + { + yield return (0, 0, 0); + yield return (0, 1, 0); + yield return (0, 2, 0); + yield return (0, 3, Eip4844Constants.DataGasPerBlob * (3 - 2)); + yield return (100000, 3, Eip4844Constants.DataGasPerBlob + 100000); + yield return (Eip4844Constants.TargetDataGasPerBlock, 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 0, 0); + yield return (Eip4844Constants.TargetDataGasPerBlock, 2, Eip4844Constants.DataGasPerBlob * 2); + } + + [TestCaseSource(nameof(ExcessDataGasTestCaseSource))] + public void Blobs_excess_data_gas_is_calculated_correctly((UInt256 parentExcessDataGas, int newBlobsCount, UInt256 expectedCost) testCase) + { + void Test(IReleaseSpec spec, bool areBlobsEnabled) + { + IntrinsicGasCalculator.CalculateExcessDataGas(testCase.parentExcessDataGas, testCase.newBlobsCount, spec).Should() + .Be(areBlobsEnabled ? testCase.expectedCost : null); + } + + Test(Homestead.Instance, false); + Test(Frontier.Instance, false); + Test(SpuriousDragon.Instance, false); + Test(TangerineWhistle.Instance, false); + Test(Byzantium.Instance, false); + Test(Constantinople.Instance, false); + Test(ConstantinopleFix.Instance, false); + Test(Istanbul.Instance, false); + Test(MuirGlacier.Instance, false); + Test(Berlin.Instance, false); + Test(GrayGlacier.Instance, false); + Test(Shanghai.Instance, false); + Test(Cancun.Instance, true); + } + + public static IEnumerable<(Transaction tx, UInt256 parentExcessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() + { + yield return (Build.A.Transaction.TestObject, 0, 0); + yield return (Build.A.Transaction.TestObject, 1000, 0); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(0).TestObject, 1000, 0); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 0, 131072); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 10000000, 11665408); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 0, 131072000); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 10000000, 11665408000); + } + + [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] + public void Blobs_intrinsic_cost_is_calculated_properly( + (Transaction tx, UInt256 parentExcessDataGas, UInt256 expectedCost) testCase) + { + IntrinsicGasCalculator.CalculateDataGasPrice(testCase.tx, testCase.parentExcessDataGas).Should() + .Be(testCase.expectedCost); } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs index b7c0f6d2f32..bc262d2d110 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs @@ -7,18 +7,16 @@ using Nethermind.Core; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; -using Nethermind.Int256; using Nethermind.Logging; using Nethermind.Specs; -using Nethermind.Specs.Forks; using Nethermind.State; using Nethermind.Trie.Pruning; -using NSubstitute; using NUnit.Framework; namespace Nethermind.Evm.Test.Tracing @@ -42,9 +40,12 @@ public void Does_not_take_into_account_precompiles() Transaction tx = Build.A.Transaction.WithGasLimit(1000).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Call, true); - testEnvironment.tracer.ReportActionEnd(400, Array.Empty()); // this would not happen but we want to ensure that precompiles are ignored + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Call, true); + testEnvironment.tracer.ReportActionEnd(400, + Array.Empty()); // this would not happen but we want to ensure that precompiles are ignored testEnvironment.tracer.ReportActionEnd(600, Array.Empty()); testEnvironment.estimator.Estimate(tx, block.Header, testEnvironment.tracer).Should().Be(0); @@ -72,7 +73,8 @@ public void Handles_well_top_level() Transaction tx = Build.A.Transaction.WithGasLimit(1000).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); testEnvironment.tracer.ReportActionEnd(600, Array.Empty()); testEnvironment.estimator.Estimate(tx, block.Header, testEnvironment.tracer).Should().Be(0); @@ -85,10 +87,13 @@ public void Handles_well_serial_calls() Transaction tx = Build.A.Transaction.WithGasLimit(1000).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + _executionType, false); testEnvironment.tracer.ReportActionEnd(400, Array.Empty()); - testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, + false); if (_executionType.IsAnyCreate()) { testEnvironment.tracer.ReportActionEnd(200, Address.Zero, Array.Empty()); @@ -110,9 +115,12 @@ public void Handles_well_errors() Transaction tx = Build.A.Transaction.WithGasLimit(1000).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); - testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + _executionType, false); + testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, + false); if (_executionType.IsAnyCreate()) { @@ -139,11 +147,14 @@ public void Handles_well_revert() Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; long gasLeft = gasLimit - 22000; - testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); gasLeft = 63 * gasLeft / 64; - testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + _executionType, false); gasLeft = 63 * gasLeft / 64; - testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(gasLeft, 0, Address.Zero, Address.Zero, Array.Empty(), + _executionType, false); if (_executionType.IsAnyCreate()) { @@ -168,8 +179,10 @@ public void Easy_one_level_case() Transaction tx = Build.A.Transaction.WithGasLimit(128).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(128, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); - testEnvironment.tracer.ReportAction(100, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(128, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(100, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, + false); testEnvironment.tracer.ReportActionEnd(63, Array.Empty()); // second level testEnvironment.tracer.ReportActionEnd(65, Array.Empty()); @@ -184,9 +197,12 @@ public void Handles_well_nested_calls_where_most_nested_defines_excess() Transaction tx = Build.A.Transaction.WithGasLimit(1000).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); - testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + _executionType, false); + testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, + false); if (_executionType.IsAnyCreate()) { @@ -211,9 +227,12 @@ public void Handles_well_nested_calls_where_least_nested_defines_excess() Transaction tx = Build.A.Transaction.WithGasLimit(1000).TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).TestObject; - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), ExecutionType.Transaction, false); - testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); - testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + ExecutionType.Transaction, false); + testEnvironment.tracer.ReportAction(1000, 0, Address.Zero, Address.Zero, Array.Empty(), + _executionType, false); + testEnvironment.tracer.ReportAction(400, 0, Address.Zero, Address.Zero, Array.Empty(), _executionType, + false); if (_executionType.IsAnyCreate()) { @@ -251,7 +270,8 @@ public TestEnvironment() _stateProvider.CommitTree(0); VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, + virtualMachine, NullBlockFinder.Instance, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); tracer = new(); diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs index 0ac0d44fa5d..958b9f75c6b 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs @@ -6,6 +6,7 @@ using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Extensions; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; using Nethermind.Db; @@ -44,7 +45,7 @@ public void Setup() VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, - LimboLogs.Instance); + NullBlockFinder.Instance, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs index bfb4470881d..9d60cb47b6c 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs @@ -24,6 +24,7 @@ using Nethermind.Trie.Pruning; using NUnit.Framework; using Nethermind.Config; +using Nethermind.Core.Test; namespace Nethermind.Evm.Test { @@ -56,7 +57,7 @@ public void Setup() _stateProvider.CommitTree(0); VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, NullBlockFinder.Instance, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index 6c756cf95d0..4456944e084 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -3,10 +3,12 @@ using System; using System.Numerics; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Core.Test; using Nethermind.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; @@ -48,6 +50,7 @@ public class VirtualMachineTestsBase protected virtual ulong Timestamp => 0UL; protected virtual ISpecProvider SpecProvider => MainnetSpecProvider.Instance; protected IReleaseSpec Spec => SpecProvider.GetSpec(BlockNumber, Timestamp); + protected IBlockFinder BlockFinder => NullBlockFinder.Instance; protected virtual ILogManager GetLogManager() { @@ -66,7 +69,7 @@ public virtual void Setup() _ethereumEcdsa = new EthereumEcdsa(SpecProvider.ChainId, logManager); IBlockhashProvider blockhashProvider = TestBlockhashProvider.Instance; Machine = new VirtualMachine(blockhashProvider, SpecProvider, logManager); - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, logManager); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, NullBlockFinder.Instance, logManager); } protected GethLikeTxTrace ExecuteAndTrace(params byte[] code) @@ -107,9 +110,11 @@ protected T Execute(T tracer, params byte[] code) where T : ITxTracer return tracer; } - protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[] code, long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0, byte[][] blobVersionedHashes = null) + protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[] code, + long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0, byte[][] blobVersionedHashes = null) { - (Block block, Transaction transaction) = PrepareTx(blockNumber, gasLimit, code, blockGasLimit: blockGasLimit, timestamp: timestamp, blobVersionedHashes: blobVersionedHashes); + (Block block, Transaction transaction) = PrepareTx(blockNumber, gasLimit, code, + blockGasLimit: blockGasLimit, timestamp: timestamp, blobVersionedHashes: blobVersionedHashes); TestAllTracerWithOutput tracer = CreateTracer(); _processor.Execute(transaction, block.Header, tracer); return tracer; @@ -167,7 +172,8 @@ protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[ return (block, transaction); } - protected (Block block, Transaction transaction) PrepareTx(long blockNumber, long gasLimit, byte[] code, byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) + protected (Block block, Transaction transaction) PrepareTx(long blockNumber, long gasLimit, byte[] code, + byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; @@ -202,7 +208,8 @@ protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[ return (block, transaction); } - protected (Block block, Transaction transaction) PrepareInitTx(long blockNumber, long gasLimit, byte[] code, SenderRecipientAndMiner senderRecipientAndMiner = null) + protected (Block block, Transaction transaction) PrepareInitTx(long blockNumber, long gasLimit, byte[] code, + SenderRecipientAndMiner senderRecipientAndMiner = null) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; TestState.CreateAccount(senderRecipientAndMiner.Sender, 100.Ether()); @@ -234,6 +241,7 @@ protected virtual Block BuildBlock(long blockNumber, SenderRecipientAndMiner sen .WithTransactions(tx is null ? new Transaction[0] : new[] { tx }) .WithGasLimit(blockGasLimit) .WithBeneficiary(senderRecipientAndMiner.Miner) + .WithExcessDataGas(0) .WithTimestamp(timestamp) .TestObject; } diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index fc7459c9c56..72cd04dc572 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -9,89 +9,136 @@ using Nethermind.Core.Specs; using Nethermind.Int256; -namespace Nethermind.Evm +namespace Nethermind.Evm; + +public static class IntrinsicGasCalculator { - public static class IntrinsicGasCalculator + public static long Calculate(Transaction transaction, IReleaseSpec releaseSpec) + { + long result = GasCostOf.Transaction; + result += DataCost(transaction, releaseSpec); + result += CreateCost(transaction, releaseSpec); + result += AccessListCost(transaction, releaseSpec); + return result; + } + + private static long CreateCost(Transaction transaction, IReleaseSpec releaseSpec) { - public static long Calculate(Transaction transaction, IReleaseSpec releaseSpec) + long createCost = 0; + if (transaction.IsContractCreation && releaseSpec.IsEip2Enabled) { - long result = GasCostOf.Transaction; - result += DataCost(transaction, releaseSpec); - result += CreateCost(transaction, releaseSpec); - result += AccessListCost(transaction, releaseSpec); - return result; + createCost += GasCostOf.TxCreate; } - private static long CreateCost(Transaction transaction, IReleaseSpec releaseSpec) + return createCost; + } + + private static long DataCost(Transaction transaction, IReleaseSpec releaseSpec) + { + long txDataNonZeroGasCost = + releaseSpec.IsEip2028Enabled ? GasCostOf.TxDataNonZeroEip2028 : GasCostOf.TxDataNonZero; + long dataCost = 0; + if (transaction.Data is not null) { - long createCost = 0; - if (transaction.IsContractCreation && releaseSpec.IsEip2Enabled) + Span data = transaction.Data.Value.Span; + for (int i = 0; i < transaction.DataLength; i++) { - createCost += GasCostOf.TxCreate; + dataCost += data[i] == 0 ? GasCostOf.TxDataZero : txDataNonZeroGasCost; } + } - return createCost; + if (transaction.IsContractCreation && releaseSpec.IsEip3860Enabled) + { + dataCost += EvmPooledMemory.Div32Ceiling((UInt256)transaction.DataLength) * GasCostOf.InitCodeWord; } - private static long DataCost(Transaction transaction, IReleaseSpec releaseSpec) + return dataCost; + } + + private static long AccessListCost(Transaction transaction, IReleaseSpec releaseSpec) + { + AccessList? accessList = transaction.AccessList; + long accessListCost = 0; + if (accessList is not null) { - long txDataNonZeroGasCost = - releaseSpec.IsEip2028Enabled ? GasCostOf.TxDataNonZeroEip2028 : GasCostOf.TxDataNonZero; - long dataCost = 0; - if (transaction.Data is not null) + if (releaseSpec.UseTxAccessLists) { - Span data = transaction.Data.Value.Span; - for (int i = 0; i < transaction.DataLength; i++) + if (accessList.IsNormalized) { - dataCost += data[i] == 0 ? GasCostOf.TxDataZero : txDataNonZeroGasCost; + accessListCost += accessList.Data.Count * GasCostOf.AccessAccountListEntry; + accessListCost += accessList.Data.Sum(d => d.Value.Count) * + GasCostOf.AccessStorageListEntry; + } + else + { + foreach (object o in accessList.OrderQueue!) + { + if (o is Address) + { + accessListCost += GasCostOf.AccessAccountListEntry; + } + else + { + accessListCost += GasCostOf.AccessStorageListEntry; + } + } } } - - if (transaction.IsContractCreation && releaseSpec.IsEip3860Enabled) + else { - dataCost += EvmPooledMemory.Div32Ceiling((UInt256)transaction.DataLength) * GasCostOf.InitCodeWord; + throw new InvalidDataException( + $"Transaction with an access list received within the context of {releaseSpec.Name}. Eip-2930 is not enabled."); } - - return dataCost; } - private static long AccessListCost(Transaction transaction, IReleaseSpec releaseSpec) + return accessListCost; + } + + public static UInt256 CalculateDataGasPrice(Transaction transaction, UInt256 parentExcessDataGas) => + CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0) * GetDataGasPrice(parentExcessDataGas); + + public static UInt256 CalculateDataGas(int blobCount) => + ((ulong)blobCount * Eip4844Constants.DataGasPerBlob); + + public static UInt256 GetDataGasPrice(UInt256 parentExcessDataGas) + { + UInt256 dataGasPriceUpdateFraction = 2225652; + UInt256 minDataGasPrice = 1L; + + UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) { - AccessList? accessList = transaction.AccessList; - long accessListCost = 0; - if (accessList is not null) + UInt256 output = UInt256.Zero; + + UInt256 numAccum = factor * denominator; + + for (UInt256 i = 1; numAccum > 0; i++) { - if (releaseSpec.UseTxAccessLists) - { - if (accessList.IsNormalized) - { - accessListCost += accessList.Data.Count * GasCostOf.AccessAccountListEntry; - accessListCost += accessList.Data.Sum(d => d.Value.Count) * - GasCostOf.AccessStorageListEntry; - } - else - { - foreach (object o in accessList.OrderQueue!) - { - if (o is Address) - { - accessListCost += GasCostOf.AccessAccountListEntry; - } - else - { - accessListCost += GasCostOf.AccessStorageListEntry; - } - } - } - } - else - { - throw new InvalidDataException( - $"Transaction with an access list received within the context of {releaseSpec.Name}. Eip-2930 is not enabled."); - } + output += numAccum; + numAccum *= num; + numAccum /= i * denominator; } - return accessListCost; + return output / denominator; + } + + UInt256 scaleDueToParentExcessDataGas = + FakeExponential(minDataGasPrice, parentExcessDataGas, dataGasPriceUpdateFraction); + return scaleDueToParentExcessDataGas; + } + + public static UInt256? CalculateExcessDataGas(UInt256? parentExcessDataGas, int newBlobsCount, + IReleaseSpec releaseSpec) + { + if (!releaseSpec.IsEip4844Enabled) + { + return null; } + + UInt256 excessDataGas = parentExcessDataGas.GetValueOrDefault(); + UInt256 consumedGas = Eip4844Constants.DataGasPerBlob * (UInt256)newBlobsCount; + excessDataGas += consumedGas; + return excessDataGas < Eip4844Constants.TargetDataGasPerBlock + ? UInt256.Zero + : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs new file mode 100644 index 00000000000..3e5e3eef95d --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; + +namespace Nethermind.Evm.TransactionProcessing; + +public interface IParentBlockHeaderFinder +{ + BlockHeader? FindParentHeader(BlockHeader block); +} diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 590e5adb8d5..b84b48eed4e 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -16,7 +16,6 @@ using Nethermind.Specs; using Nethermind.State; using Nethermind.State.Tracing; -using Transaction = Nethermind.Core.Transaction; namespace Nethermind.Evm.TransactionProcessing { @@ -27,6 +26,7 @@ public class TransactionProcessor : ITransactionProcessor private readonly ISpecProvider _specProvider; private readonly IWorldState _worldState; private readonly IVirtualMachine _virtualMachine; + private readonly IParentBlockHeaderFinder _blockFinder; [Flags] private enum ExecutionOptions @@ -61,12 +61,14 @@ public TransactionProcessor( ISpecProvider? specProvider, IWorldState? worldState, IVirtualMachine? virtualMachine, + IParentBlockHeaderFinder? blockFinder, ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _worldState = worldState ?? throw new ArgumentNullException(nameof(worldState)); _virtualMachine = virtualMachine ?? throw new ArgumentNullException(nameof(virtualMachine)); + _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _ecdsa = new EthereumEcdsa(specProvider.ChainId, logManager); } @@ -241,12 +243,16 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } } - UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice; + UInt256 blobsGasCost = spec.IsEip4844Enabled + ? IntrinsicGasCalculator.CalculateDataGasPrice(transaction, _blockFinder.FindParentHeader(block)?.ExcessDataGas ?? 0) + : UInt256.Zero; + + UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice + blobsGasCost; if (notSystemTransaction) { UInt256 senderBalance = _worldState.GetBalance(caller); - if (!noValidation && ((ulong)intrinsicGas * effectiveGasPrice + value > senderBalance || + if (!noValidation && ((ulong)intrinsicGas * effectiveGasPrice + value + blobsGasCost > senderBalance || senderReservedGasPayment + value > senderBalance)) { TraceLogInvalidTx(transaction, @@ -256,7 +262,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } if (!noValidation && spec.IsEip1559Enabled && !transaction.IsFree() && - senderBalance < (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value) + (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + blobsGasCost > senderBalance) { TraceLogInvalidTx(transaction, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}"); @@ -403,8 +409,6 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra _worldState.Restore(snapshot); } - if (_logger.IsTrace) _logger.Trace("Gas spent: " + spentGas); - Address gasBeneficiary = block.GasBeneficiary; bool gasBeneficiaryNotDestroyed = substate?.DestroyList.Contains(gasBeneficiary) != true; if (statusCode == StatusCode.Failure || gasBeneficiaryNotDestroyed) diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 7bc9ddb5399..91f64b7121a 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -253,8 +253,7 @@ private void CallAndRestore( blockHeader.Number + 1, blockHeader.GasLimit, Math.Max(blockHeader.Timestamp + 1, _timestamper.UnixTime.Seconds), - Array.Empty(), - null) + Array.Empty()) : new( blockHeader.ParentHash!, blockHeader.UnclesHash!, @@ -263,8 +262,7 @@ private void CallAndRestore( blockHeader.Number, blockHeader.GasLimit, blockHeader.Timestamp, - blockHeader.ExtraData, - blockHeader.ExcessDataGas); + blockHeader.ExtraData); IReleaseSpec releaseSpec = _specProvider.GetSpec(callHeader); callHeader.BaseFeePerGas = treatBlockHeaderAsParentBlock @@ -273,9 +271,8 @@ private void CallAndRestore( if (releaseSpec.IsEip4844Enabled) { - // TODO: Calculate ExcessDataGas depending on parent ExcessDataGas and number of blobs in txs callHeader.ExcessDataGas = treatBlockHeaderAsParentBlock - ? 0 + ? IntrinsicGasCalculator.CalculateExcessDataGas(blockHeader.ExcessDataGas ?? 0, transaction.BlobVersionedHashes?.Length ?? 0, releaseSpec) : blockHeader.ExcessDataGas; } callHeader.MixHash = blockHeader.MixHash; diff --git a/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs b/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs index df5cc366bdf..c6aad7591c4 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/EthSyncingInfo.cs @@ -35,7 +35,7 @@ public EthSyncingInfo( public SyncingResult GetFullInfo() { - long bestSuggestedNumber = _blockTree.FindBestSuggestedHeader().Number; + long bestSuggestedNumber = _blockTree.FindBestSuggestedHeader()?.Number ?? 0; long headNumberOrZero = _blockTree.Head?.Number ?? 0; bool isSyncing = bestSuggestedNumber > headNumberOrZero + 8; SyncMode syncMode = _syncModeSelector.Current; diff --git a/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs b/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs index 8346128af3a..9112c25105e 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs @@ -6,44 +6,27 @@ using Nethermind.Core.Crypto; using Nethermind.Int256; -namespace Nethermind.Facade.Proxy.Models -{ - public class BlockModel - { - public UInt256 Difficulty { get; set; } - public byte[] ExtraData { get; set; } - public UInt256 GasLimit { get; set; } - public UInt256 GasUsed { get; set; } - public Keccak Hash { get; set; } - public Address Miner { get; set; } - public Keccak MixHash { get; set; } - public UInt256 Nonce { get; set; } - public UInt256 Number { get; set; } - public Keccak ParentHash { get; set; } - public Keccak ReceiptsRoot { get; set; } - public Keccak Sha3Uncles { get; set; } - public UInt256 Size { get; set; } - public Keccak StateRoot { get; set; } - public ulong Timestamp { get; set; } - public UInt256 TotalDifficulty { get; set; } - public List Transactions { get; set; } - public Keccak TransactionsRoot { get; set; } - public UInt256? ExcessDataGas { get; set; } - - public Block ToBlock() - { - Block block = new(new BlockHeader(ParentHash, Sha3Uncles, Miner, Difficulty, (long)Number, - (long)GasLimit, Timestamp, ExtraData, ExcessDataGas)); +namespace Nethermind.Facade.Proxy.Models; - block.Header.StateRoot = StateRoot; - block.Header.GasUsed = (long)GasUsed; - block.Header.Hash = Hash; - block.Header.MixHash = MixHash; - block.Header.Nonce = (ulong)Nonce; - block.Header.ReceiptsRoot = ReceiptsRoot; - block.Header.TotalDifficulty = TotalDifficulty; - block.Header.TxRoot = TransactionsRoot; - return block; - } - } +public class BlockModel +{ + public UInt256 Difficulty { get; set; } + public byte[] ExtraData { get; set; } + public UInt256 GasLimit { get; set; } + public UInt256 GasUsed { get; set; } + public Keccak Hash { get; set; } + public Address Miner { get; set; } + public Keccak MixHash { get; set; } + public UInt256 Nonce { get; set; } + public UInt256 Number { get; set; } + public Keccak ParentHash { get; set; } + public Keccak ReceiptsRoot { get; set; } + public Keccak Sha3Uncles { get; set; } + public UInt256 Size { get; set; } + public Keccak StateRoot { get; set; } + public ulong Timestamp { get; set; } + public UInt256 TotalDifficulty { get; set; } + public List Transactions { get; set; } + public Keccak TransactionsRoot { get; set; } + public UInt256? ExcessDataGas { get; set; } } diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index a8c849563b0..be9c3745ce2 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -212,6 +212,7 @@ private Task InitBlockchain() getApi.SpecProvider, worldState, virtualMachine, + getApi.BlockTree, getApi.LogManager); InitSealEngine(); @@ -230,6 +231,7 @@ private Task InitBlockchain() headerValidator, unclesValidator, getApi.SpecProvider, + getApi.BlockTree, getApi.LogManager); IChainHeadInfoProvider chainHeadInfoProvider = @@ -353,6 +355,7 @@ protected virtual BlockProcessor CreateBlockProcessor() _api.WorldState, _api.ReceiptStorage, _api.WitnessCollector, + _api.BlockTree, _api.LogManager); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 922541c2d0c..4bf607ae266 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -80,7 +80,7 @@ TransactionProcessor transactionProcessor IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor = new BlockProcessor.BlockValidationTransactionsExecutor(transactionProcessor, stateProvider); BlockProcessor blockProcessor = new(specProvider, Always.Valid, new RewardCalculator(specProvider), transactionsExecutor, - stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, LimboLogs.Instance); + stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, blockTree, LimboLogs.Instance); EthereumEcdsa ecdsa = new(specProvider.ChainId, LimboLogs.Instance); BlockchainProcessor blockchainProcessor = new( diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index b956aa649f5..494776ed543 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -65,7 +65,7 @@ public void Setup() BlockhashProvider blockhashProvider = new(_blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new(blockhashProvider, specProvider, LimboLogs.Instance); - TransactionProcessor transactionProcessor = new(specProvider, stateProvider, virtualMachine, LimboLogs.Instance); + TransactionProcessor transactionProcessor = new(specProvider, stateProvider, virtualMachine, _blockTree, LimboLogs.Instance); _poSSwitcher = Substitute.For(); BlockProcessor blockProcessor = new( @@ -76,6 +76,7 @@ public void Setup() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, + _blockTree, LimboLogs.Instance); RecoverSignatures txRecovery = new(new EthereumEcdsa(TestBlockchainIds.ChainId, LimboLogs.Instance), NullTxPool.Instance, specProvider, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index ecde467d8a8..542fe92347a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -67,6 +67,7 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) Blockchain.ReceiptStorage, dbProvider, Blockchain.SpecProvider, + Blockchain.BlockTree, Blockchain.LogManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index 552fd207632..607ec443887 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -87,6 +87,7 @@ public override IDebugRpcModule Create() _receiptStorage, _dbProvider, _specProvider, + _blockTree, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs index 21bd58a7fb1..b1c7675f8ce 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthModule.TransactionExecutor.cs @@ -139,7 +139,7 @@ private static UInt256 GetResultGas(Transaction transaction, BlockchainBridge.Ca long gas = result.GasSpent; if (result.AccessList is not null) { - // if we generated access list, we need to fix actual gas cost, as all storage was considered warm + // if we generated access list, we need to fix actual gas cost, as all storage was considered warm gas -= IntrinsicGasCalculator.Calculate(transaction, Berlin.Instance); transaction.AccessList = result.AccessList; gas += IntrinsicGasCalculator.Calculate(transaction, Berlin.Instance); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs index adf28739a1c..d9ac2edfcb0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs @@ -53,7 +53,7 @@ public override IProofRpcModule Create() _dbProvider, _trieStore, _blockTree, _specProvider, _logManager); ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _logManager); + txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _blockTree, _logManager); Tracer tracer = new( txProcessingEnv.StateProvider, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 43d8977a8e2..15200210018 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -77,6 +77,7 @@ public override ITraceRpcModule Create() _receiptStorage, _dbProvider, _specProvider, + _blockTree, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index ab2cc12b3e3..10bb5aeb841 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -224,6 +224,7 @@ protected override IBlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, + BlockTree, LogManager); return new TestBlockProcessorInterceptor(processor, _blockProcessingThrottle); @@ -242,6 +243,7 @@ private IBlockValidator CreateBlockValidator() HeaderValidator, Always.Valid, SpecProvider, + BlockTree, LogManager); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 1352d8e9d1b..37ed32cddfb 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -234,7 +234,7 @@ public Task InitNetworkProtocol() _api.UnclesValidator = new MergeUnclesValidator(_poSSwitcher, _api.UnclesValidator); _api.BlockValidator = new InvalidBlockInterceptor( new BlockValidator(_api.TxValidator, _api.HeaderValidator, _api.UnclesValidator, - _api.SpecProvider, _api.LogManager), + _api.SpecProvider, _api.BlockTree, _api.LogManager), _invalidChainTracker, _api.LogManager); _api.HealthHintService = @@ -395,6 +395,7 @@ public Task InitSynchronization() _api.HeaderValidator, _api.UnclesValidator, _api.SpecProvider, + _api.BlockTree, _api.LogManager), _invalidChainTracker, _api.LogManager); diff --git a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs index 3e6e6b235e0..c7702636a84 100644 --- a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs @@ -206,6 +206,7 @@ protected override BlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, + BlockTree, LogManager); _tracerFactory = new TracerFactory( @@ -249,6 +250,7 @@ private IBlockValidator CreateBlockValidator() headerValidator, Always.Valid, SpecProvider, + BlockTree, LogManager); } diff --git a/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs b/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs index d09f9f9955c..0e2405e2b58 100644 --- a/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs +++ b/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs @@ -49,7 +49,7 @@ public ITracer Create() _dbProvider, _trieStore, _blockTree, _specProvider, _logManager); ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _logManager); + txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _blockTree, _logManager); return CreateTracer(txProcessingEnv, chainProcessingEnv); } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs index 2208172d938..8c55985202a 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs @@ -10,7 +10,6 @@ namespace Nethermind.Serialization.Rlp { public class HeaderDecoder : IRlpValueDecoder, IRlpStreamDecoder { - public BlockHeader? Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs index 655d16f269c..47bc6f68048 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs @@ -180,6 +180,7 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh mergeHeaderValidator, Always.Valid, MainnetSpecProvider.Instance, + localBlockTree, LimboLogs.Instance); ctx.SyncServer = new SyncServer( @@ -360,6 +361,7 @@ private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) headerValidatorWithInterceptor, Always.Valid, MainnetSpecProvider.Instance, + localBlockTree, LimboLogs.Instance); ctx.SyncServer = new SyncServer( @@ -401,6 +403,7 @@ public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_nul headerValidator, Always.Valid, MainnetSpecProvider.Instance, + localBlockTree, LimboLogs.Instance); ctx.SyncServer = new SyncServer( diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index a3ca85cfec9..af185ff4379 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -281,7 +281,7 @@ private SyncTestContext CreateSyncManager(int index) Always txValidator = Always.Valid; UnclesValidator unclesValidator = new(tree, headerValidator, logManager); BlockValidator blockValidator = - new(txValidator, headerValidator, unclesValidator, specProvider, logManager); + new(txValidator, headerValidator, unclesValidator, specProvider, tree, logManager); ISyncConfig syncConfig = _synchronizerType == SynchronizerType.Fast ? SyncConfig.WithFastSync @@ -289,7 +289,7 @@ private SyncTestContext CreateSyncManager(int index) RewardCalculator rewardCalculator = new(specProvider); TransactionProcessor txProcessor = - new(specProvider, stateProvider, virtualMachine, logManager); + new(specProvider, stateProvider, virtualMachine, tree, logManager); BlockProcessor blockProcessor = new( specProvider, @@ -299,6 +299,7 @@ private SyncTestContext CreateSyncManager(int index) stateProvider, receiptStorage, NullWitnessCollector.Instance, + tree, logManager); RecoverSignatures step = new(ecdsa, txPool, specProvider, logManager); @@ -311,7 +312,7 @@ private SyncTestContext CreateSyncManager(int index) WorldState devState = new(trieStore, codeDb, logManager); VirtualMachine devEvm = new(blockhashProvider, specProvider, logManager); - TransactionProcessor devTxProcessor = new(specProvider, devState, devEvm, logManager); + TransactionProcessor devTxProcessor = new(specProvider, devState, devEvm, tree, logManager); BlockProcessor devBlockProcessor = new( specProvider, @@ -321,6 +322,7 @@ private SyncTestContext CreateSyncManager(int index) devState, receiptStorage, NullWitnessCollector.Instance, + tree, logManager); BlockchainProcessor devChainProcessor = new(tree, devBlockProcessor, step, stateReader, logManager, From 7886362d0801a8df8a60090915855b232cf22df2 Mon Sep 17 00:00:00 2001 From: spencer-tb Date: Thu, 4 May 2023 13:20:25 -0600 Subject: [PATCH 02/31] ChainSpecs/BlockProcessing: Fix syncing on Genesis block due to ExcessDataGas mismatch. --- .../Nethermind.Consensus/Processing/BlockProcessor.cs | 2 +- src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpec.cs | 2 ++ .../Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs | 3 ++- .../ChainSpecStyle/Json/ChainSpecGenesisJson.cs | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index e961ff67ddc..877835be055 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -238,7 +238,7 @@ protected virtual TxReceipt[] ProcessBlock( _stateProvider.Commit(spec); _stateProvider.RecalculateStateRoot(); - if (_specProvider.GetSpec(block.Header).IsEip4844Enabled) + if (_specProvider.GetSpec(block.Header).IsEip4844Enabled && block.Header.Number != 0) { block.Header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( _blockFinder.FindParentHeader(block.Header)?.ExcessDataGas, diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpec.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpec.cs index bd2074c021c..8dc6b19e959 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpec.cs @@ -78,5 +78,7 @@ public class ChainSpec public UInt256? TerminalTotalDifficulty { get; set; } public ulong? ShanghaiTimestamp { get; set; } + + public ulong? CancunTimestamp { get; set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs index 11c81b6eacf..979a25a18cd 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs @@ -215,6 +215,7 @@ chainSpec.Parameters.Eip1283DisableTransition is null chainSpec.ArrowGlacierBlockNumber = difficultyBombDelaysBlockNumbers?.Skip(4).FirstOrDefault(); chainSpec.GrayGlacierBlockNumber = difficultyBombDelaysBlockNumbers?.Skip(5).FirstOrDefault(); chainSpec.ShanghaiTimestamp = chainSpec.Parameters.Eip3651TransitionTimestamp; + chainSpec.CancunTimestamp = chainSpec.Parameters.Eip4844TransitionTimestamp; // TheMerge parameters chainSpec.MergeForkIdBlockNumber = chainSpec.Parameters.MergeForkIdTransition; @@ -379,7 +380,7 @@ private static void LoadGenesis(ChainSpecJson chainSpecJson, ChainSpec chainSpec bool isEip4844Enabled = chainSpecJson.Params.Eip4844TransitionTimestamp != null && genesisHeader.Timestamp >= chainSpecJson.Params.Eip4844TransitionTimestamp; if (isEip4844Enabled) - genesisHeader.ExcessDataGas ??= 0; + genesisHeader.ExcessDataGas = chainSpecJson.Genesis.ExcessDataGas; genesisHeader.AuRaStep = step; genesisHeader.AuRaSignature = auRaSignature; diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs index f1f9d63845f..9ed197ae998 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs @@ -22,5 +22,7 @@ internal class ChainSpecGenesisJson public UInt256? BaseFeePerGas { get; set; } public Keccak StateRoot { get; set; } + + public UInt256? ExcessDataGas { get; set; } } } From 2cd8bd78d6deefaea53071f584f88e51534c9d0e Mon Sep 17 00:00:00 2001 From: spencer-tb Date: Thu, 4 May 2023 18:07:29 -0600 Subject: [PATCH 03/31] TxValidator: Move KZG version check into network wrapper verification. --- src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index 923586c9dac..8e832c69d73 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -131,8 +131,7 @@ transaction.BlobVersionedHashes is null || { if (transaction.BlobVersionedHashes[i] is null || transaction.BlobVersionedHashes![i].Length != - KzgPolynomialCommitments.BytesPerBlobVersionedHash || - transaction.BlobVersionedHashes![i][0] != KzgPolynomialCommitments.KzgBlobHashVersionV1) + KzgPolynomialCommitments.BytesPerBlobVersionedHash) { return false; } From da546b483fb6d3317386d1f9d1613b09a610018f Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Tue, 9 May 2023 22:45:37 +0300 Subject: [PATCH 04/31] ExcessData gas on genesis block --- .../Validators/TxValidatorTests.cs | 15 --------------- .../Processing/BlockProcessor.cs | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 5aeaa1d09f3..ce2665e5e3d 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -377,21 +377,6 @@ private static IEnumerable BlobVersionedHashInvalidTestCases TestName = "Correct version, incorrect length", ExpectedResult = false }; - yield return new TestCaseData(MakeArray(32, 0, 0)) - { - TestName = "Incorrect version, correct length", - ExpectedResult = false - }; - yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 - 1, 0)) - { - TestName = "Incorrect version, correct length", - ExpectedResult = false - }; - yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 + 1, 0)) - { - TestName = "Incorrect version, correct length", - ExpectedResult = false - }; } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index 877835be055..d40fd801195 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -241,7 +241,7 @@ protected virtual TxReceipt[] ProcessBlock( if (_specProvider.GetSpec(block.Header).IsEip4844Enabled && block.Header.Number != 0) { block.Header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( - _blockFinder.FindParentHeader(block.Header)?.ExcessDataGas, + block.Header.IsGenesis ? 0 : _blockFinder.FindParentHeader(block.Header)?.ExcessDataGas, block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0), spec); } block.Header.StateRoot = _stateProvider.StateRoot; From 1fa67f8efb60e7d4ef046be3fb2a9481ea1e5033 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 11 May 2023 11:28:09 +0300 Subject: [PATCH 05/31] Check versioned hash earlier --- .../Validators/TxValidatorTests.cs | 31 +++++++++++++------ .../Validators/TxValidator.cs | 3 +- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index ce2665e5e3d..7e1e9bbc016 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -362,20 +362,33 @@ private static IEnumerable 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 + 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 + 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 + TestName = "Correct version, incorrect length", ExpectedResult = false + }; + yield return new TestCaseData(MakeArray(32, 0)) + { + TestName = "Incorrect version, correct length", ExpectedResult = false + }; + 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)) + { + TestName = "Incorrect version, correct length", ExpectedResult = false + }; + yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1)) + { + TestName = "Correct version, correct length", ExpectedResult = true }; } } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index 8e832c69d73..923586c9dac 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -131,7 +131,8 @@ transaction.BlobVersionedHashes is null || { if (transaction.BlobVersionedHashes[i] is null || transaction.BlobVersionedHashes![i].Length != - KzgPolynomialCommitments.BytesPerBlobVersionedHash) + KzgPolynomialCommitments.BytesPerBlobVersionedHash || + transaction.BlobVersionedHashes![i][0] != KzgPolynomialCommitments.KzgBlobHashVersionV1) { return false; } From bd49c9d2691332842420a43c9dd1e0d982f8efcc Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 1 Jun 2023 16:54:14 +0300 Subject: [PATCH 06/31] Remake gas, preview --- .../Ethereum.Test.Base/BlockchainTestBase.cs | 3 +- .../Ethereum.Test.Base/GeneralTestBase.cs | 5 -- ...sts.TestAccountAbstractionRpcBlockchain.cs | 1 - .../Producers/BlockProducerBaseTests.cs | 1 - .../Producers/DevBlockproducerTests.cs | 1 - .../Nethermind.Blockchain.Test/ReorgTests.cs | 1 - .../Validators/BlockValidatorTests.cs | 2 +- .../ShardBlobBlockValidatorTests.cs | 67 ++++++++++++++++--- .../Validators/TxValidatorTests.cs | 27 +++++--- .../Validators/WithdrawalValidatorTests.cs | 10 +-- .../CliqueBlockProducerTests.cs | 4 +- .../Processing/BlockProcessor.cs | 10 +-- .../Processing/ReadOnlyTxProcessingEnv.cs | 2 +- .../Producers/TxPoolTxSource.cs | 3 +- .../Validators/BlockValidator.cs | 50 +++++++------- .../Validators/HeaderValidator.cs | 45 ++++++++++++- .../Blockchain/TestBlockchain.cs | 3 +- .../Builders/BlockBuilder.cs | 8 ++- .../Builders/BlockHeaderBuilder.cs | 8 ++- .../Encoding/BlockDecoderTests.cs | 2 +- .../Encoding/HeaderDecoderTests.cs | 12 ++-- .../Nethermind.Core.Test/NullBlockFinder.cs | 12 ---- src/Nethermind/Nethermind.Core/Block.cs | 4 +- src/Nethermind/Nethermind.Core/BlockHeader.cs | 11 ++- .../Nethermind.Core/Eip4844Constants.cs | 8 +-- .../Eip3198BaseFeeTests.cs | 2 +- .../Eip3529RefundsTests.cs | 2 +- .../Nethermind.Evm.Test/Eip3541Tests.cs | 2 +- .../IntrinsicGasCalculatorTests.cs | 14 ++-- .../Tracing/GasEstimationTests.cs | 2 +- .../TransactionProcessorFeeTests.cs | 3 +- .../TransactionProcessorTests.cs | 2 +- .../VirtualMachineTestsBase.cs | 3 +- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 41 ++++++++---- .../TransactionProcessor.cs | 5 +- .../Nethermind.Facade/BlockchainBridge.cs | 3 +- .../Steps/InitializeBlockchain.cs | 2 - .../Modules/Trace/ParityStyleTracerTests.cs | 2 +- .../Modules/Trace/TraceRpcModule.cs | 4 +- .../EngineModuleTests.HelperFunctions.cs | 3 +- .../EngineModuleTests.Setup.cs | 1 - .../Data/ExecutionPayload.cs | 14 +++- .../Nethermind.Merge.Plugin/MergePlugin.cs | 3 +- .../MevRpcModuleTests.TestMevRpcBlockchain.cs | 1 - .../HeaderDecoder.cs | 20 ++++-- .../ChainSpecStyle/ChainSpecLoader.cs | 3 + .../Json/ChainSpecGenesisJson.cs | 3 +- .../SyncServerTests.cs | 3 - .../SyncThreadTests.cs | 6 +- 49 files changed, 284 insertions(+), 160 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs diff --git a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs index 7e17170981c..36cf366fc56 100644 --- a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs @@ -140,7 +140,7 @@ protected async Task RunTest(BlockchainTest test, Stopwatch? ITxValidator txValidator = new TxValidator(TestBlockchainIds.ChainId); IHeaderValidator headerValidator = new HeaderValidator(blockTree, Sealer, specProvider, _logManager); IUnclesValidator unclesValidator = new UnclesValidator(blockTree, headerValidator, _logManager); - IBlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, unclesValidator, specProvider, blockTree, _logManager); + IBlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, unclesValidator, specProvider, _logManager); IVirtualMachine virtualMachine = new VirtualMachine( blockhashProvider, specProvider, @@ -155,7 +155,6 @@ protected async Task RunTest(BlockchainTest test, Stopwatch? specProvider, stateProvider, virtualMachine, - blockTree, _logManager), stateProvider), stateProvider, diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index 2708cca5357..b8a23b6f2f0 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -75,15 +75,10 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) specProvider, _logManager); - IDb blockInfoDb = new MemDb(); - IBlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, - new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, _logManager); - TransactionProcessor transactionProcessor = new( specProvider, stateProvider, virtualMachine, - blockTree, _logManager); InitializeTestState(test, stateProvider, specProvider); diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs index 14306765660..bce2d346394 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs @@ -282,7 +282,6 @@ private IBlockValidator CreateBlockValidator() headerValidator, Always.Valid, SpecProvider, - BlockTree, LogManager); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.cs index 4a3f401c9a8..4b8b6ef14b7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.cs @@ -17,7 +17,6 @@ using Nethermind.State; using NSubstitute; using NUnit.Framework; -using NUnit.Framework.Internal.Execution; namespace Nethermind.Blockchain.Test.Producers { diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs index 0be0241b6c9..c607884d19b 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs @@ -67,7 +67,6 @@ public void Test() specProvider, stateProvider, virtualMachine, - blockTree, LimboLogs.Instance); BlockProcessor blockProcessor = new( specProvider, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index abd3cdc5692..4adaad94d49 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -75,7 +75,6 @@ public void Setup() specProvider, stateProvider, virtualMachine, - _blockTree, LimboLogs.Instance); BlockProcessor blockProcessor = new( diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs index ceb23dce925..2ff1e691a19 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs @@ -24,7 +24,7 @@ public void When_more_uncles_than_allowed_returns_false() releaseSpec.MaximumUncleCount = 0; ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, releaseSpec)); - BlockValidator blockValidator = new(txValidator, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(txValidator, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); bool noiseRemoved = blockValidator.ValidateSuggestedBlock(Build.A.Block.TestObject); Assert.True(noiseRemoved); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs index 42bae6c1a2e..5ece491ed81 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs @@ -1,12 +1,13 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Linq; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; -using Nethermind.Evm; using Nethermind.Logging; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -20,7 +21,7 @@ public class ShardBlobBlockValidatorTests public void Not_null_ExcessDataGas_is_invalid_pre_cancun() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.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) @@ -32,7 +33,7 @@ public void Not_null_ExcessDataGas_is_invalid_pre_cancun() 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, NullBlockFinder.Instance, LimboLogs.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) @@ -40,20 +41,64 @@ public void Null_ExcessDataGas_is_invalid_post_cancun() Assert.False(isValid); } - [TestCase(0, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob - 1, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob, ExpectedResult = true)] - [TestCase(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1, ExpectedResult = false)] - public bool Blobs_per_block_count_is_valid(int blobsCount) + //[Test] + //public void Not_null_ExcessDataGas_is_invalid_pre_cancun() + //{ + // 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 + // .WithWithdrawalsRoot(TestItem.KeccakA) + // .WithWithdrawals(TestItem.WithdrawalA_1Eth) + // .TestObject); + // Assert.False(isValid); + //} + + //[Test] + //public void Null_ExcessDataGas_is_invalid_post_cancun() + //{ + // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); + // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); + // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); + // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); + // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); + //} + //private static void TestInvalid(IReleaseSpec spec, Action with) + //{ + // 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 + // .WithWithdrawalsRoot(TestItem.KeccakA) + // .WithWithdrawals(TestItem.WithdrawalA_1Eth) + // .TestObject); + // Assert.That(isValid, Is.EqualTo()); + //} + + [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, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); return blockValidator.ValidateSuggestedBlock( Build.A.Block .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) - .WithExcessDataGas(IntrinsicGasCalculator.CalculateExcessDataGas(0, blobsCount, specProvider.GenesisSpec)!.Value) - .WithTransactions(Build.A.Transaction.WithBlobVersionedHashes(blobsCount).TestObject) + .WithTransactions(Enumerable.Range(0, (int)(dataGasUsed / Eip4844Constants.DataGasPerBlob)) + .Select(i => Build.A.Transaction.WithBlobVersionedHashes(1).TestObject).ToArray()) .TestObject); } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 7e1e9bbc016..58f94f1f992 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -364,31 +364,38 @@ private static IEnumerable BlobVersionedHashInvalidTestCases yield return new TestCaseData(MakeArray(0)) { TestName = "Empty hash", ExpectedResult = false }; yield return new TestCaseData(MakeArray(1, 1)) { - TestName = "Correct version, incorrect length", ExpectedResult = false + TestName = "Correct version, incorrect length", + ExpectedResult = false }; yield return new TestCaseData(MakeArray(31, 1)) { - TestName = "Correct version, incorrect length", ExpectedResult = false + TestName = "Correct version, incorrect length", + ExpectedResult = false }; yield return new TestCaseData(MakeArray(33, 1)) { - TestName = "Correct version, incorrect length", ExpectedResult = false + TestName = "Correct version, incorrect length", + ExpectedResult = false }; yield return new TestCaseData(MakeArray(32, 0)) { - TestName = "Incorrect version, correct length", ExpectedResult = false + TestName = "Incorrect version, correct length", + ExpectedResult = false }; yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 - 1)) { - TestName = "Incorrect version, correct length", ExpectedResult = false + TestName = "Incorrect version, correct length", + ExpectedResult = false }; yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1 + 1)) { - TestName = "Incorrect version, correct length", ExpectedResult = false + TestName = "Incorrect version, correct length", + ExpectedResult = false }; yield return new TestCaseData(MakeArray(32, KzgPolynomialCommitments.KzgBlobHashVersionV1)) { - TestName = "Correct version, correct length", ExpectedResult = true + TestName = "Correct version, correct length", + ExpectedResult = true }; } } @@ -447,19 +454,19 @@ static TransactionBuilder MakeTestObject(int blobCount = 1) => Buil TestName = "More than minimum BlobVersionedHashes", ExpectedResult = true }; - yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob - 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.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob) + yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob)) .SignedAndResolved().TestObject) { TestName = "Maximum BlobVersionedHashes", ExpectedResult = true }; - yield return new TestCaseData(MakeTestObject(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1) + yield return new TestCaseData(MakeTestObject((int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob + 1)) .SignedAndResolved().TestObject) { TestName = "Too many BlobVersionedHashes", diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs index d3c69cba1b7..881480f3367 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs @@ -21,7 +21,7 @@ public class WithdrawalValidatorTests public void Not_null_withdrawals_are_invalid_pre_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, London.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(new Withdrawal[] { TestItem.WithdrawalA_1Eth, TestItem.WithdrawalB_2Eth }).TestObject); Assert.False(isValid); } @@ -30,7 +30,7 @@ public void Not_null_withdrawals_are_invalid_pre_shanghai() public void Null_withdrawals_are_invalid_post_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.TestObject); Assert.False(isValid); } @@ -39,7 +39,7 @@ public void Null_withdrawals_are_invalid_post_shanghai() public void Withdrawals_with_incorrect_withdrawals_root_are_invalid() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); Withdrawal[] withdrawals = { TestItem.WithdrawalA_1Eth, TestItem.WithdrawalB_2Eth }; Keccak withdrawalRoot = new WithdrawalTrie(withdrawals).RootHash; bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(withdrawals).WithWithdrawalsRoot(TestItem.KeccakD).TestObject); @@ -50,7 +50,7 @@ public void Withdrawals_with_incorrect_withdrawals_root_are_invalid() public void Empty_withdrawals_are_valid_post_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); Withdrawal[] withdrawals = { }; Keccak withdrawalRoot = new WithdrawalTrie(withdrawals).RootHash; bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(withdrawals).WithWithdrawalsRoot(withdrawalRoot).TestObject); @@ -61,7 +61,7 @@ public void Empty_withdrawals_are_valid_post_shanghai() public void Correct_withdrawals_block_post_shanghai() { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Shanghai.Instance)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, NullBlockFinder.Instance, LimboLogs.Instance); + BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance); Withdrawal[] withdrawals = { TestItem.WithdrawalA_1Eth, TestItem.WithdrawalB_2Eth }; Keccak withdrawalRoot = new WithdrawalTrie(withdrawals).RootHash; bool isValid = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithWithdrawals(withdrawals).WithWithdrawalsRoot(withdrawalRoot).TestObject); diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs index 225cb230d60..0340c85d171 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs @@ -122,7 +122,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f _genesis3Validators.Header.Hash = _genesis3Validators.Header.CalculateHash(); TransactionProcessor transactionProcessor = new(goerliSpecProvider, stateProvider, - new VirtualMachine(blockhashProvider, specProvider, nodeLogManager), blockTree, + new VirtualMachine(blockhashProvider, specProvider, nodeLogManager), nodeLogManager); BlockProcessor blockProcessor = new( goerliSpecProvider, @@ -142,7 +142,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f WorldState minerStateProvider = new(minerTrieStore, codeDb, nodeLogManager); VirtualMachine minerVirtualMachine = new(blockhashProvider, specProvider, nodeLogManager); - TransactionProcessor minerTransactionProcessor = new(goerliSpecProvider, minerStateProvider, minerVirtualMachine, blockTree, nodeLogManager); + TransactionProcessor minerTransactionProcessor = new(goerliSpecProvider, minerStateProvider, minerVirtualMachine, nodeLogManager); BlockProcessor minerBlockProcessor = new( goerliSpecProvider, diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index d40fd801195..5970912fecb 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -238,11 +238,12 @@ protected virtual TxReceipt[] ProcessBlock( _stateProvider.Commit(spec); _stateProvider.RecalculateStateRoot(); - if (_specProvider.GetSpec(block.Header).IsEip4844Enabled && block.Header.Number != 0) + if (spec.IsEip4844Enabled && block.Header.Number != 0) { + block.Header.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas( + block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); block.Header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( - block.Header.IsGenesis ? 0 : _blockFinder.FindParentHeader(block.Header)?.ExcessDataGas, - block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0), spec); + block.Header.IsGenesis ? null : _blockFinder.FindParentHeader(block.Header), spec); } block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = block.Header.CalculateHash(); @@ -271,7 +272,8 @@ private Block PrepareBlockForProcessing(Block suggestedBlock) bh.GasLimit, bh.Timestamp, bh.ExtraData, - bh.ExcessDataGas) + bh.ExcessDataGas, + bh.DataGasUsed) { Bloom = Bloom.Empty, Author = bh.Author, diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs index 9b8b1748e65..f99c5f01b12 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyTxProcessingEnv.cs @@ -56,7 +56,7 @@ public ReadOnlyTxProcessingEnv( BlockhashProvider = new BlockhashProvider(BlockTree, logManager); Machine = new VirtualMachine(BlockhashProvider, specProvider, logManager); - TransactionProcessor = new TransactionProcessor(specProvider, StateProvider, Machine, BlockTree, logManager); + TransactionProcessor = new TransactionProcessor(specProvider, StateProvider, Machine, logManager); } public IReadOnlyTransactionProcessor Build(Keccak stateRoot) => new ReadOnlyTransactionProcessor(TransactionProcessor, StateProvider, stateRoot); diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index f27869ad6c0..1577c309c6b 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -79,7 +79,8 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi if (tx.SupportsBlobs) { - dataGasPrice ??= IntrinsicGasCalculator.GetDataGasPrice(parent.ExcessDataGas.GetValueOrDefault()); + dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPricePerUnit( + IntrinsicGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()) ?? 0); int txAmountOfBlobs = tx.BlobVersionedHashes?.Length ?? 0; if (dataGasPrice > tx.MaxFeePerDataGas) { diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index bfae38e4676..30534bcb83b 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -22,7 +22,6 @@ public class BlockValidator : IBlockValidator private readonly ITxValidator _txValidator; private readonly IUnclesValidator _unclesValidator; private readonly ISpecProvider _specProvider; - private readonly IBlockFinder _blockFinder; private readonly ILogger _logger; public BlockValidator( @@ -30,14 +29,12 @@ public BlockValidator( IHeaderValidator? headerValidator, IUnclesValidator? unclesValidator, ISpecProvider? specProvider, - IBlockFinder? blockFinder, ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _txValidator = txValidator ?? throw new ArgumentNullException(nameof(txValidator)); _unclesValidator = unclesValidator ?? throw new ArgumentNullException(nameof(unclesValidator)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); - _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _headerValidator = headerValidator ?? throw new ArgumentNullException(nameof(headerValidator)); } @@ -106,7 +103,7 @@ public bool ValidateSuggestedBlock(Block block) if (!ValidateWithdrawals(block, spec, out _)) return false; - if (!ValidateBlobsAndExcessDataGas(block, spec, out _)) + if (!ValidateTransactionsDataGas(block, spec, out _)) return false; return true; @@ -204,46 +201,49 @@ private bool ValidateWithdrawals(Block block, IReleaseSpec spec, out string? err return true; } - private bool ValidateBlobsAndExcessDataGas(Block block, IReleaseSpec spec, out string? error) + private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out string? error) { - if (spec.IsEip4844Enabled && block.ExcessDataGas is null) + if (!spec.IsEip4844Enabled) { - error = "ExcessDataGas field is not set."; - if (_logger.IsWarn) _logger.Warn(error); - return false; - } - - if (!spec.IsEip4844Enabled && block.ExcessDataGas is not null) - { - error = "ExcessDataGas field should not have value."; - if (_logger.IsWarn) _logger.Warn(error); - return false; + error = null; + return true; } int blobsInBlock = 0; + UInt256? dataGasPrice = null; for (int txIndex = block.Transactions.Length - 1; txIndex >= 0; txIndex--) { - blobsInBlock += block.Transactions[txIndex].BlobVersionedHashes?.Length ?? 0; + Transaction transaction = block.Transactions[txIndex]; + if (!transaction.SupportsBlobs) + { + continue; + } + + if (transaction.MaxFeePerDataGas < (dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPrice(block.Header))) + { + error = $"A transactions has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } + + blobsInBlock += transaction.BlobVersionedHashes!.Length; } - if (IntrinsicGasCalculator.CalculateDataGas(blobsInBlock) > Eip4844Constants.MaxDataGasPerBlock) + ulong dataGasUsed = IntrinsicGasCalculator.CalculateDataGas(blobsInBlock); + if (dataGasUsed > Eip4844Constants.MaxDataGasPerBlock) { error = $"A block cannot have more than {Eip4844Constants.MaxDataGasPerBlock} data gas."; if (_logger.IsWarn) _logger.Warn(error); return false; } - UInt256? expectedExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( - (block.ParentHash is null ? null : _blockFinder.FindParentHeader(block.Header, BlockTreeLookupOptions.All)) - ?.ExcessDataGas, - blobsInBlock, spec); - - if (block.ExcessDataGas != expectedExcessDataGas) + if (dataGasUsed != block.Header.DataGasUsed) { - error = $"ExcessDataGas field is incorrect: {block.ExcessDataGas}, should be {expectedExcessDataGas}."; + error = $"DataGasUsed does not match actuall data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; if (_logger.IsWarn) _logger.Warn(error); return false; } + error = null; return true; } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs index ee708ce6aff..4c93be57a0c 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Int256; using Nethermind.Logging; @@ -123,6 +124,8 @@ public virtual bool Validate(BlockHeader header, BlockHeader? parent, bool isUnc } } + bool eip4844Valid = ValidateDataGasFields(header, parent, spec); + return totalDifficultyCorrect && gasUsedBelowLimit && @@ -133,7 +136,8 @@ public virtual bool Validate(BlockHeader header, BlockHeader? parent, bool isUnc numberIsParentPlusOne && hashAsExpected && extraDataValid && - eip1559Valid; + eip1559Valid && + eip4844Valid; } private bool ValidateFieldLimit(BlockHeader blockHeader) @@ -277,5 +281,44 @@ private bool ValidateGenesis(BlockHeader header) header.Bloom is not null && header.ExtraData.Length <= _specProvider.GenesisSpec.MaximumExtraDataSize; } + + private bool ValidateDataGasFields(BlockHeader header, BlockHeader parentHeader, IReleaseSpec spec) + { + if (spec.IsEip4844Enabled && header.ExcessDataGas is null) + { + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is not set."); + return false; + } + + if (spec.IsEip4844Enabled && header.DataGasUsed is null) + { + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field is not set."); + return false; + } + + if (!spec.IsEip4844Enabled) + { + if (header.ExcessDataGas is not null) + { + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field should not have value."); + return false; + } + if (header.DataGasUsed is not null) + { + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field should not have value."); + return false; + } + return true; + } + + UInt256? expectedExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parentHeader, spec); + + if (header.ExcessDataGas != expectedExcessDataGas) + { + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is incorrect: {header.ExcessDataGas}, should be {expectedExcessDataGas}."); + return false; + } + return true; + } } } diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index c9fa5e28fb2..6e8a41a35d8 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -149,7 +149,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = ReceiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new(new BlockhashProvider(BlockTree, LogManager), SpecProvider, LogManager); - TxProcessor = new TransactionProcessor(SpecProvider, State, virtualMachine, BlockTree, LogManager); + TxProcessor = new TransactionProcessor(SpecProvider, State, virtualMachine, LogManager); BlockPreprocessorStep = new RecoverSignatures(EthereumEcdsa, TxPool, SpecProvider, LogManager); HeaderValidator = new HeaderValidator(BlockTree, Always.Valid, SpecProvider, LogManager); @@ -160,7 +160,6 @@ protected virtual async Task Build(ISpecProvider? specProvider = HeaderValidator, Always.Valid, SpecProvider, - BlockTree, LogManager); PoSSwitcher = NoPoS.Instance; diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs index f25730883f4..017f5cd88be 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs @@ -56,12 +56,18 @@ public BlockBuilder WithTimestamp(ulong timestamp) return this; } - public BlockBuilder WithExcessDataGas(UInt256 excessDataGas) + public BlockBuilder WithExcessDataGas(ulong? excessDataGas) { TestObjectInternal.Header.ExcessDataGas = excessDataGas; return this; } + public BlockBuilder WithDataGasUsed(ulong? dataGasUsed) + { + TestObjectInternal.Header.DataGasUsed = dataGasUsed; + return this; + } + public BlockBuilder WithTransactions(int txCount, IReleaseSpec releaseSpec) { Transaction[] txs = new Transaction[txCount]; diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs index 3b301cf9f1a..496705b6306 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs @@ -179,9 +179,15 @@ public BlockHeaderBuilder WithWithdrawalsRoot(Keccak? root) return this; } - public BlockHeaderBuilder WithExcessDataGas(UInt256? excessDataGas) + public BlockHeaderBuilder WithExcessDataGas(ulong? excessDataGas) { TestObjectInternal.ExcessDataGas = excessDataGas; return this; } + + public BlockHeaderBuilder WithDataGasUsed(ulong? dataGasUsed) + { + TestObjectInternal.DataGasUsed = dataGasUsed; + return this; + } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs index 0bccc8b6b12..77374b04067 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs @@ -81,7 +81,7 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) - .WithExcessDataGas(UInt256.MaxValue) + .WithExcessDataGas(ulong.MaxValue) .WithMixHash(Keccak.EmptyTreeHash) .TestObject }; diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs index efe802ca17a..0e993f382ab 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs @@ -129,7 +129,7 @@ public void If_withdrawals_are_null_should_not_encode() } [TestCaseSource(nameof(ExcessDataGasCaseSource))] - public void Can_encode_decode_with_excessDataGas(UInt256? excessDataGas) + public void Can_encode_decode_with_excessDataGas(ulong? excessDataGas) { BlockHeader header = Build.A.BlockHeader .WithTimestamp(ulong.MaxValue) @@ -143,13 +143,13 @@ public void Can_encode_decode_with_excessDataGas(UInt256? excessDataGas) blockHeader.ExcessDataGas.Should().Be(excessDataGas); } - public static IEnumerable ExcessDataGasCaseSource() + public static IEnumerable ExcessDataGasCaseSource() { yield return null; - yield return UInt256.Zero; - yield return new UInt256(1); - yield return UInt256.UInt128MaxValue; - yield return UInt256.MaxValue; + yield return 0ul; + yield return 1ul; + yield return ulong.MaxValue / 2; + yield return ulong.MaxValue; } [TestCase(-1)] diff --git a/src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs b/src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs deleted file mode 100644 index c6de442298e..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/NullBlockFinder.cs +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Blockchain.Find; -using NSubstitute; - -namespace Nethermind.Core.Test; - -public static class NullBlockFinder -{ - public static IBlockFinder Instance = Substitute.For(); -} diff --git a/src/Nethermind/Nethermind.Core/Block.cs b/src/Nethermind/Nethermind.Core/Block.cs index fe2d08fdb8e..fdabd68844f 100644 --- a/src/Nethermind/Nethermind.Core/Block.cs +++ b/src/Nethermind/Nethermind.Core/Block.cs @@ -98,7 +98,9 @@ public Transaction[] Transactions public UInt256 BaseFeePerGas => Header.BaseFeePerGas; // do not add setter here - public UInt256? ExcessDataGas => Header.ExcessDataGas; // do not add setter here + public ulong? ExcessDataGas => Header.ExcessDataGas; // do not add setter here + + public ulong? DataGasUsed => Header.DataGasUsed; // do not add setter here public bool IsPostMerge => Header.IsPostMerge; // do not add setter here diff --git a/src/Nethermind/Nethermind.Core/BlockHeader.cs b/src/Nethermind/Nethermind.Core/BlockHeader.cs index c85150f9274..1f5f7922c48 100644 --- a/src/Nethermind/Nethermind.Core/BlockHeader.cs +++ b/src/Nethermind/Nethermind.Core/BlockHeader.cs @@ -25,7 +25,10 @@ public BlockHeader( long gasLimit, ulong timestamp, byte[] extraData, - UInt256? excessDataGas = null) + //ulong? excessDataGas, + //ulong? dataGasUsed) + ulong? excessDataGas = null, + ulong? dataGasUsed = null) { ParentHash = parentHash; UnclesHash = unclesHash; @@ -36,6 +39,7 @@ public BlockHeader( Timestamp = timestamp; ExtraData = extraData; ExcessDataGas = excessDataGas; + DataGasUsed = dataGasUsed; } public WeakReference? MaybeParent { get; set; } @@ -65,8 +69,8 @@ public BlockHeader( public long? AuRaStep { get; set; } public UInt256 BaseFeePerGas { get; set; } public Keccak? WithdrawalsRoot { get; set; } - public UInt256? ExcessDataGas { get; set; } - + public ulong? ExcessDataGas { get; set; } + public ulong? DataGasUsed { get; set; } public bool HasBody => (TxRoot is not null && TxRoot != Keccak.EmptyTreeHash) || (UnclesHash is not null && UnclesHash != Keccak.OfAnEmptySequenceRlp) || (WithdrawalsRoot is not null && WithdrawalsRoot != Keccak.EmptyTreeHash); @@ -102,6 +106,7 @@ public string ToString(string indent) if (ExcessDataGas is not null) { builder.AppendLine($"{indent}ExcessDataGas: {ExcessDataGas}"); + builder.AppendLine($"{indent}DataGasUsed: {DataGasUsed}"); } builder.AppendLine($"{indent}IsPostMerge: {IsPostMerge}"); builder.AppendLine($"{indent}TotalDifficulty: {TotalDifficulty}"); diff --git a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs index 84da26216e1..c631ee943f8 100644 --- a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs @@ -10,8 +10,8 @@ public class Eip4844Constants { public const int MinBlobsPerTransaction = 1; - public const int DataGasPerBlob = 1 << 17; - public const int TargetDataGasPerBlock = 1 << 18; - public const int MaxDataGasPerBlock = 1 << 19; - public const int MaxDataGasPerTransaction = MaxDataGasPerBlock; + public const ulong DataGasPerBlob = 1 << 17; + public const ulong TargetDataGasPerBlock = 1 << 18; + public const ulong MaxDataGasPerBlock = 1 << 19; + public const ulong MaxDataGasPerTransaction = MaxDataGasPerBlock; } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs index c787a8d031e..64d8b5810e3 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs @@ -29,7 +29,7 @@ public class Eip3198BaseFeeTests : VirtualMachineTestsBase [TestCase(false, 0, false)] public void Base_fee_opcode_should_return_expected_results(bool eip3198Enabled, int baseFee, bool send1559Tx) { - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, NullBlockFinder.Instance, LimboLogs.Instance); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); byte[] code = Prepare.EvmCode .Op(Instruction.BASEFEE) .PushData(0) diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs index bde2edc9816..fe3e7a58e32 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3529RefundsTests.cs @@ -73,7 +73,7 @@ private void Test(string codeHex, long gasUsed, long refund, byte originalValue, TestState.CreateAccount(Recipient, 1.Ether()); TestState.Set(new StorageCell(Recipient, 0), new[] { originalValue }); TestState.Commit(eip3529Enabled ? London.Instance : Berlin.Instance); - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, BlockFinder, LimboLogs.Instance); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); long blockNumber = eip3529Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, Bytes.FromHexString(codeHex)); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs index bf0adb8c348..bef8582a4be 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3541Tests.cs @@ -100,7 +100,7 @@ void DeployCodeAndAssertTx(string code, bool eip3541Enabled, ContractDeployment break; } - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, BlockFinder, LimboLogs.Instance); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); long blockNumber = eip3541Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, createContract); diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index 02717cc9f70..158c123c184 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -116,7 +116,7 @@ void Test(IReleaseSpec spec, bool isAfterRepricing) Test(Cancun.Instance, true); } - public static IEnumerable<(UInt256 parentExcessDataGas, int newBlobsCount, UInt256 expectedCost)> ExcessDataGasTestCaseSource() + public static IEnumerable<(ulong parentExcessDataGas, int newBlobsCount, ulong expectedCost)> ExcessDataGasTestCaseSource() { yield return (0, 0, 0); yield return (0, 1, 0); @@ -129,11 +129,12 @@ void Test(IReleaseSpec spec, bool isAfterRepricing) } [TestCaseSource(nameof(ExcessDataGasTestCaseSource))] - public void Blobs_excess_data_gas_is_calculated_correctly((UInt256 parentExcessDataGas, int newBlobsCount, UInt256 expectedCost) testCase) + public void Blobs_excess_data_gas_is_calculated_correctly((ulong excessDataGas, int newBlobsCount, ulong expectedCost) testCase) { void Test(IReleaseSpec spec, bool areBlobsEnabled) { - IntrinsicGasCalculator.CalculateExcessDataGas(testCase.parentExcessDataGas, testCase.newBlobsCount, spec).Should() + BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; + IntrinsicGasCalculator.CalculateExcessDataGas(header, spec).Should() .Be(areBlobsEnabled ? testCase.expectedCost : null); } @@ -152,7 +153,7 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) Test(Cancun.Instance, true); } - public static IEnumerable<(Transaction tx, UInt256 parentExcessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() + public static IEnumerable<(Transaction tx, ulong excessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() { yield return (Build.A.Transaction.TestObject, 0, 0); yield return (Build.A.Transaction.TestObject, 1000, 0); @@ -165,9 +166,10 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] public void Blobs_intrinsic_cost_is_calculated_properly( - (Transaction tx, UInt256 parentExcessDataGas, UInt256 expectedCost) testCase) + (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) { - IntrinsicGasCalculator.CalculateDataGasPrice(testCase.tx, testCase.parentExcessDataGas).Should() + BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; + IntrinsicGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() .Be(testCase.expectedCost); } } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs index bc262d2d110..eb9021f38f8 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/GasEstimationTests.cs @@ -271,7 +271,7 @@ public TestEnvironment() VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, - virtualMachine, NullBlockFinder.Instance, LimboLogs.Instance); + virtualMachine, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); tracer = new(); diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs index 958b9f75c6b..e64c27bfcea 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorFeeTests.cs @@ -44,8 +44,7 @@ public void Setup() _stateProvider.CommitTree(0); VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, - NullBlockFinder.Instance, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs index 9d60cb47b6c..21fffcb574e 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs @@ -57,7 +57,7 @@ public void Setup() _stateProvider.CommitTree(0); VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); - _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, NullBlockFinder.Instance, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index 4456944e084..85a6a5f9f5a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -50,7 +50,6 @@ public class VirtualMachineTestsBase protected virtual ulong Timestamp => 0UL; protected virtual ISpecProvider SpecProvider => MainnetSpecProvider.Instance; protected IReleaseSpec Spec => SpecProvider.GetSpec(BlockNumber, Timestamp); - protected IBlockFinder BlockFinder => NullBlockFinder.Instance; protected virtual ILogManager GetLogManager() { @@ -69,7 +68,7 @@ public virtual void Setup() _ethereumEcdsa = new EthereumEcdsa(SpecProvider.ChainId, logManager); IBlockhashProvider blockhashProvider = TestBlockhashProvider.Instance; Machine = new VirtualMachine(blockhashProvider, SpecProvider, logManager); - _processor = new TransactionProcessor(SpecProvider, TestState, Machine, NullBlockFinder.Instance, logManager); + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, logManager); } protected GethLikeTxTrace ExecuteAndTrace(params byte[] code) diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index 72cd04dc572..10f71605ec2 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -94,13 +94,27 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release return accessListCost; } - public static UInt256 CalculateDataGasPrice(Transaction transaction, UInt256 parentExcessDataGas) => - CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0) * GetDataGasPrice(parentExcessDataGas); + public static ulong CalculateDataGas(int blobCount) => (ulong)blobCount * Eip4844Constants.DataGasPerBlob; - public static UInt256 CalculateDataGas(int blobCount) => - ((ulong)blobCount * Eip4844Constants.DataGasPerBlob); + public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => + CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0) * CalculateDataGasPrice(header); - public static UInt256 GetDataGasPrice(UInt256 parentExcessDataGas) + public static UInt256 CalculateDataGasPrice(BlockHeader header) => + header.DataGasUsed.Value * CalculateDataGasPrice(header); + + public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) + { + if (header.ExcessDataGas is null) + { + throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)); + } + + ulong excessDataGas = header.ExcessDataGas.Value; + + return CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); + } + + public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) { UInt256 dataGasPriceUpdateFraction = 2225652; UInt256 minDataGasPrice = 1L; @@ -122,23 +136,26 @@ UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) } UInt256 scaleDueToParentExcessDataGas = - FakeExponential(minDataGasPrice, parentExcessDataGas, dataGasPriceUpdateFraction); + FakeExponential(minDataGasPrice, excessDataGas, dataGasPriceUpdateFraction); return scaleDueToParentExcessDataGas; } - public static UInt256? CalculateExcessDataGas(UInt256? parentExcessDataGas, int newBlobsCount, - IReleaseSpec releaseSpec) + public static ulong? CalculateExcessDataGas(BlockHeader? parentBlockHeader, IReleaseSpec releaseSpec) { if (!releaseSpec.IsEip4844Enabled) { return null; } - UInt256 excessDataGas = parentExcessDataGas.GetValueOrDefault(); - UInt256 consumedGas = Eip4844Constants.DataGasPerBlob * (UInt256)newBlobsCount; - excessDataGas += consumedGas; + if (parentBlockHeader is null) + { + return 0; + } + + ulong excessDataGas = parentBlockHeader.ExcessDataGas ?? 0; + excessDataGas += parentBlockHeader.DataGasUsed ?? 0; return excessDataGas < Eip4844Constants.TargetDataGasPerBlock - ? UInt256.Zero + ? 0 : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index b84b48eed4e..523daf6ff63 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -26,7 +26,6 @@ public class TransactionProcessor : ITransactionProcessor private readonly ISpecProvider _specProvider; private readonly IWorldState _worldState; private readonly IVirtualMachine _virtualMachine; - private readonly IParentBlockHeaderFinder _blockFinder; [Flags] private enum ExecutionOptions @@ -61,14 +60,12 @@ public TransactionProcessor( ISpecProvider? specProvider, IWorldState? worldState, IVirtualMachine? virtualMachine, - IParentBlockHeaderFinder? blockFinder, ILogManager? logManager) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _worldState = worldState ?? throw new ArgumentNullException(nameof(worldState)); _virtualMachine = virtualMachine ?? throw new ArgumentNullException(nameof(virtualMachine)); - _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _ecdsa = new EthereumEcdsa(specProvider.ChainId, logManager); } @@ -244,7 +241,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } UInt256 blobsGasCost = spec.IsEip4844Enabled - ? IntrinsicGasCalculator.CalculateDataGasPrice(transaction, _blockFinder.FindParentHeader(block)?.ExcessDataGas ?? 0) + ? IntrinsicGasCalculator.CalculateDataGasPrice(block, transaction) : UInt256.Zero; UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice + blobsGasCost; diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 91f64b7121a..0746848502a 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -271,8 +271,9 @@ private void CallAndRestore( if (releaseSpec.IsEip4844Enabled) { + callHeader.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); callHeader.ExcessDataGas = treatBlockHeaderAsParentBlock - ? IntrinsicGasCalculator.CalculateExcessDataGas(blockHeader.ExcessDataGas ?? 0, transaction.BlobVersionedHashes?.Length ?? 0, releaseSpec) + ? IntrinsicGasCalculator.CalculateExcessDataGas(blockHeader, releaseSpec) : blockHeader.ExcessDataGas; } callHeader.MixHash = blockHeader.MixHash; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index be9c3745ce2..cbc8c754a9b 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -212,7 +212,6 @@ private Task InitBlockchain() getApi.SpecProvider, worldState, virtualMachine, - getApi.BlockTree, getApi.LogManager); InitSealEngine(); @@ -231,7 +230,6 @@ private Task InitBlockchain() headerValidator, unclesValidator, getApi.SpecProvider, - getApi.BlockTree, getApi.LogManager); IChainHeadInfoProvider chainHeadInfoProvider = diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index 494776ed543..f44e3a96002 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -65,7 +65,7 @@ public void Setup() BlockhashProvider blockhashProvider = new(_blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new(blockhashProvider, specProvider, LimboLogs.Instance); - TransactionProcessor transactionProcessor = new(specProvider, stateProvider, virtualMachine, _blockTree, LimboLogs.Instance); + TransactionProcessor transactionProcessor = new(specProvider, stateProvider, virtualMachine, LimboLogs.Instance); _poSSwitcher = Substitute.For(); BlockProcessor blockProcessor = new( diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index ebaf494751c..06d9f0cd916 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -129,7 +129,9 @@ private SearchResult SearchBlockHeaderForTraceCall(BlockParameter b header.Number + 1, header.GasLimit, header.Timestamp + 1, - header.ExtraData); + header.ExtraData, + header.ExcessDataGas, + header.DataGasUsed); header.TotalDifficulty = 2 * header.Difficulty; header.BaseFeePerGas = baseFee; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index 5a91099f04d..2b51887417c 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -84,7 +84,7 @@ private ExecutionPayload CreateParentBlockRequestOnHead(IBlockTree blockTree) }; } - private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList? withdrawals = null, UInt256? excessDataGas = null, Transaction[]? transactions = null) + private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? excessDataGas = null, ulong? dataGasUsed = null, Transaction[]? transactions = null) { ExecutionPayload blockRequest = new() { @@ -99,6 +99,7 @@ private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Addr Timestamp = parent.Timestamp + 1, Withdrawals = withdrawals, ExcessDataGas = excessDataGas, + DataGasUsed = dataGasUsed, }; blockRequest.SetTransactions(transactions ?? Array.Empty()); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index 10bb5aeb841..63d056f3ca9 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -243,7 +243,6 @@ private IBlockValidator CreateBlockValidator() HeaderValidator, Always.Valid, SpecProvider, - BlockTree, LogManager); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs index c541f003b92..8b9e8f1874f 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs @@ -98,7 +98,14 @@ public byte[][] Transactions /// EIP-4844. /// [JsonProperty(ItemConverterType = typeof(NullableUInt256Converter), NullValueHandling = NullValueHandling.Ignore)] - public UInt256? ExcessDataGas { get; set; } + public ulong? ExcessDataGas { get; set; } + + /// + /// Gets or sets as defined in + /// EIP-4844. + /// + [JsonProperty(ItemConverterType = typeof(NullableUInt256Converter), NullValueHandling = NullValueHandling.Ignore)] + public ulong? DataGasUsed { get; set; } /// /// Creates the execution block from payload. @@ -119,7 +126,9 @@ public virtual bool TryGetBlock(out Block? block, UInt256? totalDifficulty = nul BlockNumber, GasLimit, Timestamp, - ExtraData) + ExtraData, + ExcessDataGas, + DataGasUsed) { Hash = BlockHash, ReceiptsRoot = ReceiptsRoot, @@ -134,7 +143,6 @@ public virtual bool TryGetBlock(out Block? block, UInt256? totalDifficulty = nul TotalDifficulty = totalDifficulty, TxRoot = new TxTrie(transactions).RootHash, WithdrawalsRoot = Withdrawals is null ? null : new WithdrawalTrie(Withdrawals).RootHash, - ExcessDataGas = ExcessDataGas, }; block = new(header, transactions, Array.Empty(), Withdrawals); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 37ed32cddfb..1352d8e9d1b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -234,7 +234,7 @@ public Task InitNetworkProtocol() _api.UnclesValidator = new MergeUnclesValidator(_poSSwitcher, _api.UnclesValidator); _api.BlockValidator = new InvalidBlockInterceptor( new BlockValidator(_api.TxValidator, _api.HeaderValidator, _api.UnclesValidator, - _api.SpecProvider, _api.BlockTree, _api.LogManager), + _api.SpecProvider, _api.LogManager), _invalidChainTracker, _api.LogManager); _api.HealthHintService = @@ -395,7 +395,6 @@ public Task InitSynchronization() _api.HeaderValidator, _api.UnclesValidator, _api.SpecProvider, - _api.BlockTree, _api.LogManager), _invalidChainTracker, _api.LogManager); diff --git a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs index c7702636a84..a8825ba9063 100644 --- a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs @@ -250,7 +250,6 @@ private IBlockValidator CreateBlockValidator() headerValidator, Always.Valid, SpecProvider, - BlockTree, LogManager); } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs index 8c55985202a..2580b2b2cd3 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs @@ -71,15 +71,16 @@ public class HeaderDecoder : IRlpValueDecoder, IRlpStreamDecoder 0 && decoderContext.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.WithdrawalsRoot = decoderContext.DecodeKeccak(); - if (itemsRemaining == 2 && decoderContext.Position != headerCheck) + if (itemsRemaining == 3 && decoderContext.Position != headerCheck) { - blockHeader.ExcessDataGas = decoderContext.DecodeUInt256(); + blockHeader.DataGasUsed = decoderContext.DecodeULong(); + blockHeader.ExcessDataGas = decoderContext.DecodeULong(); } } @@ -151,15 +152,16 @@ public class HeaderDecoder : IRlpValueDecoder, IRlpStreamDecoder 0 && rlpStream.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.WithdrawalsRoot = rlpStream.DecodeKeccak(); - if (itemsRemaining == 2 && rlpStream.Position != headerCheck) + if (itemsRemaining == 3 && rlpStream.Position != headerCheck) { - blockHeader.ExcessDataGas = rlpStream.DecodeUInt256(); + blockHeader.DataGasUsed = rlpStream.DecodeUlong(allowLeadingZeroBytes: false); + blockHeader.ExcessDataGas = rlpStream.DecodeUlong(allowLeadingZeroBytes: false); } } @@ -220,6 +222,11 @@ public void Encode(RlpStream rlpStream, BlockHeader? header, RlpBehaviors rlpBeh rlpStream.Encode(header.WithdrawalsRoot ?? Keccak.Zero); } + if (header.DataGasUsed is not null) + { + rlpStream.Encode(header.DataGasUsed.Value); + } + if (header.ExcessDataGas is not null) { rlpStream.Encode(header.ExcessDataGas.Value); @@ -263,6 +270,7 @@ private static int GetContentLength(BlockHeader? item, RlpBehaviors rlpBehaviors + Rlp.LengthOf(item.ExtraData) + (item.BaseFeePerGas.IsZero ? 0 : Rlp.LengthOf(item.BaseFeePerGas)) + (item.WithdrawalsRoot is null && item.ExcessDataGas is null ? 0 : Rlp.LengthOfKeccakRlp) + + (item.DataGasUsed is null ? 0 : Rlp.LengthOf(item.DataGasUsed.Value)) + (item.ExcessDataGas is null ? 0 : Rlp.LengthOf(item.ExcessDataGas.Value)); if (notForSealing) diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs index 979a25a18cd..d464f67f4bb 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs @@ -380,7 +380,10 @@ private static void LoadGenesis(ChainSpecJson chainSpecJson, ChainSpec chainSpec bool isEip4844Enabled = chainSpecJson.Params.Eip4844TransitionTimestamp != null && genesisHeader.Timestamp >= chainSpecJson.Params.Eip4844TransitionTimestamp; if (isEip4844Enabled) + { genesisHeader.ExcessDataGas = chainSpecJson.Genesis.ExcessDataGas; + genesisHeader.DataGasUsed = chainSpecJson.Genesis.DataGasUsed; + } genesisHeader.AuRaStep = step; genesisHeader.AuRaSignature = auRaSignature; diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs index 9ed197ae998..e44df546b35 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs @@ -23,6 +23,7 @@ internal class ChainSpecGenesisJson public Keccak StateRoot { get; set; } - public UInt256? ExcessDataGas { get; set; } + public ulong? ExcessDataGas { get; set; } + public ulong? DataGasUsed { get; set; } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs index 47bc6f68048..655d16f269c 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs @@ -180,7 +180,6 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh mergeHeaderValidator, Always.Valid, MainnetSpecProvider.Instance, - localBlockTree, LimboLogs.Instance); ctx.SyncServer = new SyncServer( @@ -361,7 +360,6 @@ private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) headerValidatorWithInterceptor, Always.Valid, MainnetSpecProvider.Instance, - localBlockTree, LimboLogs.Instance); ctx.SyncServer = new SyncServer( @@ -403,7 +401,6 @@ public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_nul headerValidator, Always.Valid, MainnetSpecProvider.Instance, - localBlockTree, LimboLogs.Instance); ctx.SyncServer = new SyncServer( diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index af185ff4379..05dd2db8983 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -281,7 +281,7 @@ private SyncTestContext CreateSyncManager(int index) Always txValidator = Always.Valid; UnclesValidator unclesValidator = new(tree, headerValidator, logManager); BlockValidator blockValidator = - new(txValidator, headerValidator, unclesValidator, specProvider, tree, logManager); + new(txValidator, headerValidator, unclesValidator, specProvider, logManager); ISyncConfig syncConfig = _synchronizerType == SynchronizerType.Fast ? SyncConfig.WithFastSync @@ -289,7 +289,7 @@ private SyncTestContext CreateSyncManager(int index) RewardCalculator rewardCalculator = new(specProvider); TransactionProcessor txProcessor = - new(specProvider, stateProvider, virtualMachine, tree, logManager); + new(specProvider, stateProvider, virtualMachine, logManager); BlockProcessor blockProcessor = new( specProvider, @@ -312,7 +312,7 @@ private SyncTestContext CreateSyncManager(int index) WorldState devState = new(trieStore, codeDb, logManager); VirtualMachine devEvm = new(blockhashProvider, specProvider, logManager); - TransactionProcessor devTxProcessor = new(specProvider, devState, devEvm, tree, logManager); + TransactionProcessor devTxProcessor = new(specProvider, devState, devEvm, logManager); BlockProcessor devBlockProcessor = new( specProvider, From a7120a83ecb30e869c341e3526df98844985e7d8 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Sat, 3 Jun 2023 20:18:57 +0300 Subject: [PATCH 07/31] Fix recursion --- src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index 10f71605ec2..5b1b6ce0b7e 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -97,10 +97,10 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release public static ulong CalculateDataGas(int blobCount) => (ulong)blobCount * Eip4844Constants.DataGasPerBlob; public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => - CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0) * CalculateDataGasPrice(header); + CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0) * CalculateDataGasPricePerUnit(header); public static UInt256 CalculateDataGasPrice(BlockHeader header) => - header.DataGasUsed.Value * CalculateDataGasPrice(header); + header.DataGasUsed.Value * CalculateDataGasPricePerUnit(header); public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) { From 6630c963f84488d1ab60ba1f5bc9f559778e7dde Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 14:13:51 +0300 Subject: [PATCH 08/31] Add tests, refactor --- .../ShardBlobBlockValidatorTests.cs | 119 +++++++++--------- .../Processing/BlockProcessor.cs | 24 ++-- .../Producers/BlockProducerBase.cs | 3 +- .../Validators/BlockValidator.cs | 5 + .../Validators/HeaderValidator.cs | 21 ++-- .../Blockchain/TestBlockchain.cs | 3 +- .../Builders/BlockBuilder.cs | 8 +- .../Builders/BlockHeaderBuilder.cs | 11 +- .../Encoding/BlockDecoderTests.cs | 3 + .../Encoding/HeaderDecoderTests.cs | 16 +-- src/Nethermind/Nethermind.Core/Block.cs | 4 +- src/Nethermind/Nethermind.Core/BlockHeader.cs | 12 +- .../IntrinsicGasCalculatorTests.cs | 4 +- .../VirtualMachineTestsBase.cs | 1 + .../Nethermind.Evm/IntrinsicGasCalculator.cs | 2 - .../TransactionProcessor.cs | 8 +- .../Modules/Eth/BlockForRpc.cs | 6 +- .../Modules/Trace/TraceRpcModule.cs | 4 +- .../EngineModuleTests.HelperFunctions.cs | 4 +- .../EngineModuleTests.V3.cs | 2 +- .../Data/ExecutionPayload.cs | 4 +- .../HeaderDecoder.cs | 14 +-- .../ChainSpecStyle/ChainSpecLoader.cs | 2 +- 23 files changed, 146 insertions(+), 134 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs index 5ece491ed81..2ba597d41b8 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections; +using System.Collections.Generic; using System.Linq; using Nethermind.Consensus.Validators; using Nethermind.Core; @@ -17,74 +19,19 @@ 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)); + ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec)); 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 + return blockValidator.ValidateSuggestedBlock(Build.A.Block + .WithDataGasUsed(dataGasUsed) + .WithExcessDataGas(excessDataGas) .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) .TestObject); - Assert.False(isValid); } - //[Test] - //public void Not_null_ExcessDataGas_is_invalid_pre_cancun() - //{ - // 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 - // .WithWithdrawalsRoot(TestItem.KeccakA) - // .WithWithdrawals(TestItem.WithdrawalA_1Eth) - // .TestObject); - // Assert.False(isValid); - //} - - //[Test] - //public void Null_ExcessDataGas_is_invalid_post_cancun() - //{ - // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); - // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); - // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); - // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); - // TestInvalid(Cancun.Instance, b => b.WithExcessDataGas(0).WithDataGasUsed(0)); - //} - //private static void TestInvalid(IReleaseSpec spec, Action with) - //{ - // 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 - // .WithWithdrawalsRoot(TestItem.KeccakA) - // .WithWithdrawals(TestItem.WithdrawalA_1Eth) - // .TestObject); - // Assert.That(isValid, Is.EqualTo()); - //} - [TestCase(0ul, ExpectedResult = true)] [TestCase(Eip4844Constants.MaxDataGasPerBlock - Eip4844Constants.DataGasPerBlob, ExpectedResult = true)] [TestCase(Eip4844Constants.MaxDataGasPerBlock, ExpectedResult = true)] @@ -97,8 +44,58 @@ public bool Blobs_per_block_count_is_valid(ulong dataGasUsed) Build.A.Block .WithWithdrawalsRoot(TestItem.KeccakA) .WithWithdrawals(TestItem.WithdrawalA_1Eth) + .WithDataGasUsed(dataGasUsed) .WithTransactions(Enumerable.Range(0, (int)(dataGasUsed / Eip4844Constants.DataGasPerBlob)) .Select(i => Build.A.Transaction.WithBlobVersionedHashes(1).TestObject).ToArray()) .TestObject); } + + public static IEnumerable DataGasFieldsPerForkTestCases + { + get + { + yield return new TestCaseData(Shanghai.Instance, null, null) + { + TestName = "Not set pre-Cancun", + ExpectedResult = true + }; + yield return new TestCaseData(Shanghai.Instance, 1ul, null) + { + TestName = "DataGasUsed is improperly set pre-Cancun", + ExpectedResult = false + }; + yield return new TestCaseData(Shanghai.Instance, null, 1ul) + { + TestName = "ExcessDataGas is improperly set pre-Cancun", + ExpectedResult = false + }; + yield return new TestCaseData(Shanghai.Instance, 1ul, 1ul) + { + TestName = "Data gas field are improperly set pre-Cancun", + ExpectedResult = false + }; + + + yield return new TestCaseData(Cancun.Instance, null, null) + { + TestName = "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, 1ul, 1ul) + { + TestName = "Data gas fields are set post-Cancun", + ExpectedResult = true + }; + } + } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index 5970912fecb..70b9d0dd4bb 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -228,6 +228,18 @@ protected virtual TxReceipt[] ProcessBlock( _receiptsTracer.SetOtherTracer(blockTracer); _receiptsTracer.StartNewBlockTrace(block); + + if (spec.IsEip4844Enabled && block.Header.Number != 0) + { + block.Header.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas( + block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); + + if (block.Header.ExcessDataGas is null) + { + throw new ApplicationException("ExcessDataGas cannot be null"); + } + } + TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, _receiptsTracer, spec); block.Header.ReceiptsRoot = receipts.GetReceiptsRoot(spec, block.ReceiptsRoot); @@ -238,13 +250,7 @@ protected virtual TxReceipt[] ProcessBlock( _stateProvider.Commit(spec); _stateProvider.RecalculateStateRoot(); - if (spec.IsEip4844Enabled && block.Header.Number != 0) - { - block.Header.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas( - block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); - block.Header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas( - block.Header.IsGenesis ? null : _blockFinder.FindParentHeader(block.Header), spec); - } + block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = block.Header.CalculateHash(); @@ -272,8 +278,8 @@ private Block PrepareBlockForProcessing(Block suggestedBlock) bh.GasLimit, bh.Timestamp, bh.ExtraData, - bh.ExcessDataGas, - bh.DataGasUsed) + bh.DataGasUsed, + bh.ExcessDataGas) { Bloom = Bloom.Empty, Author = bh.Author, diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index 4d2033798db..6d6fbc4c426 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -303,7 +303,8 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, if (Logger.IsDebug) Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}."); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); - + header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetSpec(header)); + return header; } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 30534bcb83b..adc6d14a169 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -145,6 +145,11 @@ public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, B if (_logger.IsError) _logger.Error($"- state root: expected {suggestedBlock.Header.StateRoot}, got {processedBlock.Header.StateRoot}"); } + if (processedBlock.Header.DataGasUsed != suggestedBlock.Header.DataGasUsed) + { + if (_logger.IsError) _logger.Error($"- data gas used: expected {suggestedBlock.Header.DataGasUsed}, got {processedBlock.Header.DataGasUsed}"); + } + if (processedBlock.Header.ExcessDataGas != suggestedBlock.Header.ExcessDataGas) { if (_logger.IsError) _logger.Error($"- excess data gas: expected {suggestedBlock.Header.ExcessDataGas}, got {processedBlock.Header.ExcessDataGas}"); diff --git a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs index 4c93be57a0c..d06440ae66c 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs @@ -2,12 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; -using System.Linq; using Nethermind.Blockchain; using Nethermind.Blockchain.Find; using Nethermind.Core; -using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; @@ -284,30 +281,32 @@ header.Bloom is not null && private bool ValidateDataGasFields(BlockHeader header, BlockHeader parentHeader, IReleaseSpec spec) { - if (spec.IsEip4844Enabled && header.ExcessDataGas is null) + if (spec.IsEip4844Enabled && header.DataGasUsed is null) { - if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is not set."); + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field is not set."); return false; } - if (spec.IsEip4844Enabled && header.DataGasUsed is null) + if (spec.IsEip4844Enabled && header.ExcessDataGas is null) { - if (_logger.IsWarn) _logger.Warn($"DataGasUsed field is not set."); + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is not set."); return false; } if (!spec.IsEip4844Enabled) { - if (header.ExcessDataGas is not null) + if (header.DataGasUsed is not null) { - if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field should not have value."); + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field should not have value."); return false; } - if (header.DataGasUsed is not null) + + if (header.ExcessDataGas is not null) { - if (_logger.IsWarn) _logger.Warn($"DataGasUsed field should not have value."); + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field should not have value."); return false; } + return true; } diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 6e8a41a35d8..f8ed5740892 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -293,13 +293,14 @@ protected virtual Block GetGenesisBlock() } genesisBlockBuilder.WithStateRoot(State.StateRoot); - if (SealEngineType == Nethermind.Core.SealEngineType.AuRa) + if (SealEngineType == Core.SealEngineType.AuRa) { genesisBlockBuilder.WithAura(0, new byte[65]); } if (SpecProvider.GenesisSpec.IsEip4844Enabled) { + genesisBlockBuilder.WithDataGasUsed(0); genesisBlockBuilder.WithExcessDataGas(0); } diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs index 017f5cd88be..445553e93d7 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs @@ -56,15 +56,15 @@ public BlockBuilder WithTimestamp(ulong timestamp) return this; } - public BlockBuilder WithExcessDataGas(ulong? excessDataGas) + public BlockBuilder WithDataGasUsed(ulong? dataGasUsed) { - TestObjectInternal.Header.ExcessDataGas = excessDataGas; + TestObjectInternal.Header.DataGasUsed = dataGasUsed; return this; } - public BlockBuilder WithDataGasUsed(ulong? dataGasUsed) + public BlockBuilder WithExcessDataGas(ulong? excessDataGas) { - TestObjectInternal.Header.DataGasUsed = dataGasUsed; + TestObjectInternal.Header.ExcessDataGas = excessDataGas; return this; } diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs index 496705b6306..dfc12b82659 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockHeaderBuilder.cs @@ -30,8 +30,7 @@ public BlockHeaderBuilder() DefaultDifficulty, 0, 4_000_000, 1_000_000, - new byte[] { 1, 2, 3 }, - null); + new byte[] { 1, 2, 3 }); TestObjectInternal.Bloom = Bloom.Empty; TestObjectInternal.MixHash = Keccak.Compute("mix_hash"); TestObjectInternal.Nonce = 1000; @@ -179,15 +178,15 @@ public BlockHeaderBuilder WithWithdrawalsRoot(Keccak? root) return this; } - public BlockHeaderBuilder WithExcessDataGas(ulong? excessDataGas) + public BlockHeaderBuilder WithDataGasUsed(ulong? dataGasUsed) { - TestObjectInternal.ExcessDataGas = excessDataGas; + TestObjectInternal.DataGasUsed = dataGasUsed; return this; } - public BlockHeaderBuilder WithDataGasUsed(ulong? dataGasUsed) + public BlockHeaderBuilder WithExcessDataGas(ulong? excessDataGas) { - TestObjectInternal.DataGasUsed = dataGasUsed; + TestObjectInternal.ExcessDataGas = excessDataGas; return this; } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs index 77374b04067..26626ad9769 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockDecoderTests.cs @@ -63,6 +63,7 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) + .WithDataGasUsed(0) .WithExcessDataGas(0) .WithMixHash(Keccak.EmptyTreeHash) .TestObject, @@ -72,6 +73,7 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) + .WithDataGasUsed(0xff) .WithExcessDataGas(0xff) .WithMixHash(Keccak.EmptyTreeHash) .TestObject, @@ -81,6 +83,7 @@ public BlockDecoderTests() .WithTransactions(transactions) .WithUncles(uncles) .WithWithdrawals(8) + .WithDataGasUsed(ulong.MaxValue) .WithExcessDataGas(ulong.MaxValue) .WithMixHash(Keccak.EmptyTreeHash) .TestObject diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs index 0e993f382ab..78ddaf49f05 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs @@ -129,27 +129,29 @@ public void If_withdrawals_are_null_should_not_encode() } [TestCaseSource(nameof(ExcessDataGasCaseSource))] - public void Can_encode_decode_with_excessDataGas(ulong? excessDataGas) + public void Can_encode_decode_with_excessDataGas(ulong? dataGasUsed, ulong? excessDataGas) { BlockHeader header = Build.A.BlockHeader .WithTimestamp(ulong.MaxValue) .WithBaseFee(1) .WithWithdrawalsRoot(Keccak.Zero) + .WithDataGasUsed(dataGasUsed) .WithExcessDataGas(excessDataGas).TestObject; Rlp rlp = Rlp.Encode(header); BlockHeader blockHeader = Rlp.Decode(rlp.Bytes.AsSpan()); + blockHeader.DataGasUsed.Should().Be(dataGasUsed); blockHeader.ExcessDataGas.Should().Be(excessDataGas); } - public static IEnumerable ExcessDataGasCaseSource() + public static IEnumerable ExcessDataGasCaseSource() { - yield return null; - yield return 0ul; - yield return 1ul; - yield return ulong.MaxValue / 2; - yield return ulong.MaxValue; + yield return new object[] { null, null }; + yield return new object[] { 0ul, 0ul }; + yield return new object[] { 1ul, 2ul }; + yield return new object[] { ulong.MaxValue / 2, ulong.MaxValue }; + yield return new object[] { ulong.MaxValue, ulong.MaxValue / 2 }; } [TestCase(-1)] diff --git a/src/Nethermind/Nethermind.Core/Block.cs b/src/Nethermind/Nethermind.Core/Block.cs index fdabd68844f..59e9ed916bb 100644 --- a/src/Nethermind/Nethermind.Core/Block.cs +++ b/src/Nethermind/Nethermind.Core/Block.cs @@ -98,10 +98,10 @@ public Transaction[] Transactions public UInt256 BaseFeePerGas => Header.BaseFeePerGas; // do not add setter here - public ulong? ExcessDataGas => Header.ExcessDataGas; // do not add setter here - public ulong? DataGasUsed => Header.DataGasUsed; // do not add setter here + public ulong? ExcessDataGas => Header.ExcessDataGas; // do not add setter here + public bool IsPostMerge => Header.IsPostMerge; // do not add setter here public bool IsBodyMissing => Header.HasBody && Body.IsEmpty; diff --git a/src/Nethermind/Nethermind.Core/BlockHeader.cs b/src/Nethermind/Nethermind.Core/BlockHeader.cs index 1f5f7922c48..6c53d0a9a02 100644 --- a/src/Nethermind/Nethermind.Core/BlockHeader.cs +++ b/src/Nethermind/Nethermind.Core/BlockHeader.cs @@ -25,10 +25,8 @@ public BlockHeader( long gasLimit, ulong timestamp, byte[] extraData, - //ulong? excessDataGas, - //ulong? dataGasUsed) - ulong? excessDataGas = null, - ulong? dataGasUsed = null) + ulong? dataGasUsed = null, + ulong? excessDataGas = null) { ParentHash = parentHash; UnclesHash = unclesHash; @@ -38,8 +36,8 @@ public BlockHeader( GasLimit = gasLimit; Timestamp = timestamp; ExtraData = extraData; - ExcessDataGas = excessDataGas; DataGasUsed = dataGasUsed; + ExcessDataGas = excessDataGas; } public WeakReference? MaybeParent { get; set; } @@ -103,10 +101,10 @@ public string ToString(string indent) { builder.AppendLine($"{indent}WithdrawalsRoot: {WithdrawalsRoot}"); } - if (ExcessDataGas is not null) + if (DataGasUsed is not null || ExcessDataGas is not null) { - builder.AppendLine($"{indent}ExcessDataGas: {ExcessDataGas}"); builder.AppendLine($"{indent}DataGasUsed: {DataGasUsed}"); + builder.AppendLine($"{indent}ExcessDataGas: {ExcessDataGas}"); } builder.AppendLine($"{indent}IsPostMerge: {IsPostMerge}"); builder.AppendLine($"{indent}TotalDifficulty: {TotalDifficulty}"); diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index 158c123c184..a561975011f 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -133,7 +133,9 @@ public void Blobs_excess_data_gas_is_calculated_correctly((ulong excessDataGas, { void Test(IReleaseSpec spec, bool areBlobsEnabled) { - BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; + BlockHeader header = Build.A.BlockHeader + .WithDataGasUsed(IntrinsicGasCalculator.CalculateDataGas(testCase.newBlobsCount)) + .WithExcessDataGas(testCase.excessDataGas).TestObject; IntrinsicGasCalculator.CalculateExcessDataGas(header, spec).Should() .Be(areBlobsEnabled ? testCase.expectedCost : null); } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index 85a6a5f9f5a..10bd69c260a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -240,6 +240,7 @@ protected virtual Block BuildBlock(long blockNumber, SenderRecipientAndMiner sen .WithTransactions(tx is null ? new Transaction[0] : new[] { tx }) .WithGasLimit(blockGasLimit) .WithBeneficiary(senderRecipientAndMiner.Miner) + .WithDataGasUsed(0) .WithExcessDataGas(0) .WithTimestamp(timestamp) .TestObject; diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index 5b1b6ce0b7e..08e46ad6ee0 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -109,8 +109,6 @@ public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)); } - ulong excessDataGas = header.ExcessDataGas.Value; - return CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 523daf6ff63..e30b9fc3887 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -240,16 +240,16 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } } - UInt256 blobsGasCost = spec.IsEip4844Enabled + UInt256 dataGasPrice = spec.IsEip4844Enabled ? IntrinsicGasCalculator.CalculateDataGasPrice(block, transaction) : UInt256.Zero; - UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice + blobsGasCost; + UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice + dataGasPrice; if (notSystemTransaction) { UInt256 senderBalance = _worldState.GetBalance(caller); - if (!noValidation && ((ulong)intrinsicGas * effectiveGasPrice + value + blobsGasCost > senderBalance || + if (!noValidation && ((ulong)intrinsicGas * effectiveGasPrice + value + dataGasPrice > senderBalance || senderReservedGasPayment + value > senderBalance)) { TraceLogInvalidTx(transaction, @@ -259,7 +259,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } if (!noValidation && spec.IsEip1559Enabled && !transaction.IsFree() && - (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + blobsGasCost > senderBalance) + (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + dataGasPrice > senderBalance) { TraceLogInvalidTx(transaction, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}"); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs index f2f8eda9a44..6e9a82cf353 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/BlockForRpc.cs @@ -58,6 +58,7 @@ public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider s if (spec.IsEip4844Enabled) { + DataGasUsed = block.Header.DataGasUsed; ExcessDataGas = block.Header.ExcessDataGas; } } @@ -125,5 +126,8 @@ public BlockForRpc(Block block, bool includeFullTransactionData, ISpecProvider s public Keccak? WithdrawalsRoot { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public UInt256? ExcessDataGas { get; set; } + public ulong? DataGasUsed { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? ExcessDataGas { get; set; } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 06d9f0cd916..92799bf6d51 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -130,8 +130,8 @@ private SearchResult SearchBlockHeaderForTraceCall(BlockParameter b header.GasLimit, header.Timestamp + 1, header.ExtraData, - header.ExcessDataGas, - header.DataGasUsed); + header.DataGasUsed, + header.ExcessDataGas); header.TotalDifficulty = 2 * header.Difficulty; header.BaseFeePerGas = baseFee; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index 2b51887417c..36459b7444e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -84,7 +84,7 @@ private ExecutionPayload CreateParentBlockRequestOnHead(IBlockTree blockTree) }; } - private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? excessDataGas = null, ulong? dataGasUsed = null, Transaction[]? transactions = null) + private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? dataGasUsed = null, ulong? excessDataGas = null, Transaction[]? transactions = null) { ExecutionPayload blockRequest = new() { @@ -98,8 +98,8 @@ private static ExecutionPayload CreateBlockRequest(ExecutionPayload parent, Addr LogsBloom = Bloom.Empty, Timestamp = parent.Timestamp + 1, Withdrawals = withdrawals, - ExcessDataGas = excessDataGas, DataGasUsed = dataGasUsed, + ExcessDataGas = excessDataGas, }; blockRequest.SetTransactions(transactions ?? Array.Empty()); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index bfa5a3c99c3..dd25c68e9e5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -223,7 +223,7 @@ public static IEnumerable BlobVersionedHashesDoNotMatchTestSource private async Task SendNewBlockV3(IEngineRpcModule rpc, MergeTestBlockchain chain, IList? withdrawals) { ExecutionPayload executionPayload = CreateBlockRequest( - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals, 0); + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals, 0, 0); ResultWrapper executePayloadResult = await rpc.engine_newPayloadV3(executionPayload, Array.Empty()); executePayloadResult.Data.Status.Should().Be(PayloadStatus.Valid); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs index 8b9e8f1874f..feb086c0d7d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs @@ -127,8 +127,8 @@ public virtual bool TryGetBlock(out Block? block, UInt256? totalDifficulty = nul GasLimit, Timestamp, ExtraData, - ExcessDataGas, - DataGasUsed) + DataGasUsed, + ExcessDataGas) { Hash = BlockHash, ReceiptsRoot = ReceiptsRoot, diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs index 2580b2b2cd3..d6d1ef9fa62 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs @@ -217,19 +217,15 @@ public void Encode(RlpStream rlpStream, BlockHeader? header, RlpBehaviors rlpBeh rlpStream.Encode(header.BaseFeePerGas); } - if (header.WithdrawalsRoot is not null || header.ExcessDataGas is not null) + if (header.WithdrawalsRoot is not null || header.ExcessDataGas is not null || header.DataGasUsed is not null) { rlpStream.Encode(header.WithdrawalsRoot ?? Keccak.Zero); } - if (header.DataGasUsed is not null) + if (header.DataGasUsed is not null || header.ExcessDataGas is not null) { - rlpStream.Encode(header.DataGasUsed.Value); - } - - if (header.ExcessDataGas is not null) - { - rlpStream.Encode(header.ExcessDataGas.Value); + rlpStream.Encode(header.DataGasUsed.GetValueOrDefault()); + rlpStream.Encode(header.ExcessDataGas.GetValueOrDefault()); } } @@ -269,7 +265,7 @@ private static int GetContentLength(BlockHeader? item, RlpBehaviors rlpBehaviors + Rlp.LengthOf(item.Timestamp) + Rlp.LengthOf(item.ExtraData) + (item.BaseFeePerGas.IsZero ? 0 : Rlp.LengthOf(item.BaseFeePerGas)) - + (item.WithdrawalsRoot is null && item.ExcessDataGas is null ? 0 : Rlp.LengthOfKeccakRlp) + + (item.WithdrawalsRoot is null && item.DataGasUsed is null && item.ExcessDataGas is null ? 0 : Rlp.LengthOfKeccakRlp) + (item.DataGasUsed is null ? 0 : Rlp.LengthOf(item.DataGasUsed.Value)) + (item.ExcessDataGas is null ? 0 : Rlp.LengthOf(item.ExcessDataGas.Value)); diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs index d464f67f4bb..360e1cada75 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs @@ -381,8 +381,8 @@ private static void LoadGenesis(ChainSpecJson chainSpecJson, ChainSpec chainSpec bool isEip4844Enabled = chainSpecJson.Params.Eip4844TransitionTimestamp != null && genesisHeader.Timestamp >= chainSpecJson.Params.Eip4844TransitionTimestamp; if (isEip4844Enabled) { - genesisHeader.ExcessDataGas = chainSpecJson.Genesis.ExcessDataGas; genesisHeader.DataGasUsed = chainSpecJson.Genesis.DataGasUsed; + genesisHeader.ExcessDataGas = chainSpecJson.Genesis.ExcessDataGas; } genesisHeader.AuRaStep = step; From f363565ff11ad1790e8cb8a9eb115e9c34b31555 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 15:16:50 +0300 Subject: [PATCH 09/31] Get rid of parent block header finder --- ...sts.TestAccountAbstractionRpcBlockchain.cs | 1 - .../BlockProcessorTests.cs | 3 -- .../Producers/DevBlockproducerTests.cs | 1 - .../Nethermind.Blockchain.Test/ReorgTests.cs | 1 - .../ShardBlobBlockValidatorTests.cs | 30 +++++++++--------- .../Nethermind.Blockchain/BlockTree.cs | 5 --- .../Find/IBlockFinder.cs | 2 +- .../ReadOnlyBlockTree.cs | 5 --- .../CliqueBlockProducerTests.cs | 2 -- .../AuRaBlockProcessor.cs | 3 -- .../CliquePlugin.cs | 1 - .../NethDevPlugin.cs | 1 - .../Processing/BlockProcessor.cs | 3 -- .../Processing/ReadOnlyChainProcessingEnv.cs | 2 -- .../Producers/BlockProducerBase.cs | 2 +- .../Producers/BlockProducerEnvFactory.cs | 1 - .../Validators/BlockValidator.cs | 31 +++++++++++++++++-- .../Blockchain/TestBlockchain.cs | 1 - .../IParentBlockHeaderFinder.cs | 11 ------- .../Steps/InitializeBlockchain.cs | 1 - .../Modules/Trace/ParityStyleTracerTests.cs | 1 - .../Modules/TraceRpcModuleTests.cs | 1 - .../Modules/DebugModule/DebugModuleFactory.cs | 1 - .../Modules/Proof/ProofModuleFactory.cs | 2 +- .../Modules/Trace/TraceModuleFactory.cs | 1 - .../EngineModuleTests.Setup.cs | 1 - .../MevRpcModuleTests.TestMevRpcBlockchain.cs | 1 - .../Nethermind.Mev/Execution/TracerFactory.cs | 2 +- .../SyncThreadTests.cs | 2 -- 29 files changed, 48 insertions(+), 71 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs index bce2d346394..44f0aef692c 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/AccountAbstractionRpcModuleTests.TestAccountAbstractionRpcBlockchain.cs @@ -192,7 +192,6 @@ protected override BlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, - BlockTree, LogManager); var parser = new AbiDefinitionParser(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs index ad3a7d6da8c..c8ea25143ac 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs @@ -52,7 +52,6 @@ public void Prepared_block_contains_author_field() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - Substitute.For(), LimboLogs.Instance); BlockHeader header = Build.A.BlockHeader.WithAuthor(TestItem.AddressD).TestObject; @@ -84,7 +83,6 @@ public void Can_store_a_witness() stateProvider, NullReceiptStorage.Instance, witnessCollector, - Substitute.For(), LimboLogs.Instance); BlockHeader header = Build.A.BlockHeader.WithAuthor(TestItem.AddressD).TestObject; @@ -114,7 +112,6 @@ public void Recovers_state_on_cancel() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - Substitute.For(), LimboLogs.Instance); BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithAuthor(TestItem.AddressD).TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs index c607884d19b..c8de8362917 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs @@ -76,7 +76,6 @@ public void Test() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - blockTree, LimboLogs.Instance); BlockchainProcessor blockchainProcessor = new( blockTree, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index 4adaad94d49..8795add9d9c 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -85,7 +85,6 @@ public void Setup() stateProvider, NullReceiptStorage.Instance, new WitnessCollector(memDbProvider.StateDb, LimboLogs.Instance), - _blockTree, LimboLogs.Instance); _blockchainProcessor = new BlockchainProcessor( _blockTree, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs index 2ba597d41b8..cc7f1082614 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs @@ -1,14 +1,11 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; -using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Specs.Forks; @@ -23,7 +20,7 @@ public class ShardBlobBlockValidatorTests public static bool Data_gas_fields_should_be_set(IReleaseSpec spec, ulong? dataGasUsed, ulong? excessDataGas) { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec)); - 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 .WithDataGasUsed(dataGasUsed) .WithExcessDataGas(excessDataGas) @@ -39,14 +36,17 @@ public static bool Data_gas_fields_should_be_set(IReleaseSpec spec, ulong? dataG 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) .WithDataGasUsed(dataGasUsed) + .WithExcessDataGas(0) .WithTransactions(Enumerable.Range(0, (int)(dataGasUsed / Eip4844Constants.DataGasPerBlob)) - .Select(i => Build.A.Transaction.WithBlobVersionedHashes(1).TestObject).ToArray()) + .Select(i => Build.A.Transaction.WithType(TxType.Blob) + .WithMaxFeePerDataGas(ulong.MaxValue) + .WithBlobVersionedHashes(1).TestObject).ToArray()) .TestObject); } @@ -56,29 +56,29 @@ public static IEnumerable DataGasFieldsPerForkTestCases { yield return new TestCaseData(Shanghai.Instance, null, null) { - TestName = "Not set pre-Cancun", + TestName = "Data gas fields are not set pre-Cancun", ExpectedResult = true }; - yield return new TestCaseData(Shanghai.Instance, 1ul, null) + yield return new TestCaseData(Shanghai.Instance, 0ul, null) { - TestName = "DataGasUsed is improperly set pre-Cancun", + TestName = "DataGasUsed is set pre-Cancun", ExpectedResult = false }; - yield return new TestCaseData(Shanghai.Instance, null, 1ul) + yield return new TestCaseData(Shanghai.Instance, null, 0ul) { - TestName = "ExcessDataGas is improperly set pre-Cancun", + TestName = "ExcessDataGas is set pre-Cancun", ExpectedResult = false }; - yield return new TestCaseData(Shanghai.Instance, 1ul, 1ul) + yield return new TestCaseData(Shanghai.Instance, 0ul, 0ul) { - TestName = "Data gas field are improperly set pre-Cancun", + TestName = "Data gas fields are set pre-Cancun", ExpectedResult = false }; yield return new TestCaseData(Cancun.Instance, null, null) { - TestName = "Not set post-Cancun", + TestName = "Data gas fields are not set post-Cancun", ExpectedResult = false }; yield return new TestCaseData(Cancun.Instance, 0ul, null) @@ -91,7 +91,7 @@ public static IEnumerable DataGasFieldsPerForkTestCases TestName = "Just ExcessDataGas is set post-Cancun", ExpectedResult = false }; - yield return new TestCaseData(Cancun.Instance, 1ul, 1ul) + yield return new TestCaseData(Cancun.Instance, 0ul, 0ul) { TestName = "Data gas fields are set post-Cancun", ExpectedResult = true diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 419e00aebc0..496e084381c 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -2032,10 +2032,5 @@ public void ForkChoiceUpdated(Keccak? finalizedBlockHash, Keccak? safeBlockHash) _metadataDb.Set(MetadataDbKeys.SafeBlockHash, Rlp.Encode(SafeHash!).Bytes); } } - - BlockHeader? IParentBlockHeaderFinder.FindParentHeader(BlockHeader block) => - this.FindParentHeader(block, - BlockTreeLookupOptions.TotalDifficultyNotNeeded | BlockTreeLookupOptions.DoNotCreateLevelIfMissing | - BlockTreeLookupOptions.AllowInvalid); } } diff --git a/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs b/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs index 09487f7b671..6c31423670d 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs @@ -8,7 +8,7 @@ namespace Nethermind.Blockchain.Find { - public interface IBlockFinder : IParentBlockHeaderFinder + public interface IBlockFinder { Keccak HeadHash { get; } diff --git a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs index 1340fe5ce57..f7dc98ecea0 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs @@ -201,10 +201,5 @@ IEnumerable GetPotentiallyCorruptedBlocks(long start) public void UpdateMainChain(IReadOnlyList blocks, bool wereProcessed, bool forceHeadBlock = false) => throw new InvalidOperationException($"{nameof(ReadOnlyBlockTree)} does not expect {nameof(UpdateMainChain)} calls"); public void ForkChoiceUpdated(Keccak? finalizedBlockHash, Keccak? safeBlockBlockHash) => throw new InvalidOperationException($"{nameof(ReadOnlyBlockTree)} does not expect {nameof(ForkChoiceUpdated)} calls"); - - BlockHeader? IParentBlockHeaderFinder.FindParentHeader(BlockHeader block) => - this.FindParentHeader(block, - BlockTreeLookupOptions.TotalDifficultyNotNeeded | BlockTreeLookupOptions.DoNotCreateLevelIfMissing | - BlockTreeLookupOptions.AllowInvalid); } } diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs index 0340c85d171..b905d8e6a49 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs @@ -132,7 +132,6 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - blockTree, nodeLogManager); BlockchainProcessor processor = new(blockTree, blockProcessor, new AuthorRecoveryStep(snapshotManager), stateReader, nodeLogManager, BlockchainProcessor.Options.NoReceipts); @@ -152,7 +151,6 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f minerStateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - blockTree, nodeLogManager); BlockchainProcessor minerProcessor = new(blockTree, minerBlockProcessor, new AuthorRecoveryStep(snapshotManager), stateReader, nodeLogManager, BlockchainProcessor.Options.NoReceipts); diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 90cd7643427..1c4c5b44b22 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -14,8 +14,6 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Crypto; -using Nethermind.Db; -using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.State; @@ -54,7 +52,6 @@ public AuRaBlockProcessor( stateProvider, receiptStorage, NullWitnessCollector.Instance, - blockTree, logManager, withdrawalProcessor) { diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs index 57ccb6bb258..4180bd2a69a 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs @@ -109,7 +109,6 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd producerEnv.StateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - getFromApi.BlockTree, getFromApi.LogManager, new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(producerEnv.StateProvider, getFromApi.LogManager))); diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs index 87e2b7c6906..4db8a7d0aa6 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs @@ -81,7 +81,6 @@ public Task InitBlockProducer(IBlockProductionTrigger? blockProd producerEnv.StateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - getFromApi.BlockTree, getFromApi.LogManager); IBlockchainProcessor producerChainProcessor = new BlockchainProcessor( diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index 70b9d0dd4bb..bf52a322557 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -32,7 +32,6 @@ public partial class BlockProcessor : IBlockProcessor protected readonly IWorldState _stateProvider; private readonly IReceiptStorage _receiptStorage; private readonly IWitnessCollector _witnessCollector; - private readonly IBlockFinder _blockFinder; private readonly IWithdrawalProcessor _withdrawalProcessor; private readonly IBlockValidator _blockValidator; private readonly IRewardCalculator _rewardCalculator; @@ -54,7 +53,6 @@ public BlockProcessor( IWorldState? stateProvider, IReceiptStorage? receiptStorage, IWitnessCollector? witnessCollector, - IBlockFinder? blockFinder, ILogManager? logManager, IWithdrawalProcessor? withdrawalProcessor = null) { @@ -64,7 +62,6 @@ public BlockProcessor( _stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider)); _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); _witnessCollector = witnessCollector ?? throw new ArgumentNullException(nameof(witnessCollector)); - _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder)); _withdrawalProcessor = withdrawalProcessor ?? new WithdrawalProcessor(stateProvider, logManager); _rewardCalculator = rewardCalculator ?? throw new ArgumentNullException(nameof(rewardCalculator)); _blockTransactionsExecutor = blockTransactionsExecutor ?? throw new ArgumentNullException(nameof(blockTransactionsExecutor)); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs index 513951438d1..acb585b4d72 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs @@ -35,7 +35,6 @@ public ReadOnlyChainProcessingEnv( IReceiptStorage receiptStorage, IReadOnlyDbProvider dbProvider, ISpecProvider specProvider, - IBlockFinder blockFinder, ILogManager logManager, IBlockProcessor.IBlockTransactionsExecutor? blockTransactionsExecutor = null) { @@ -52,7 +51,6 @@ public ReadOnlyChainProcessingEnv( StateProvider, receiptStorage, NullWitnessCollector.Instance, - blockFinder, logManager); _blockProcessingQueue = new BlockchainProcessor(_txEnv.BlockTree, BlockProcessor, recoveryStep, _txEnv.StateReader, logManager, BlockchainProcessor.Options.NoReceipts); diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index 6d6fbc4c426..bf02f7ebba0 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -304,7 +304,7 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, if (Logger.IsDebug) Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}."); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetSpec(header)); - + return header; } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index d6bb5a54a0c..65820969f0e 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -149,7 +149,6 @@ protected virtual BlockProcessor CreateBlockProcessor(ReadOnlyTxProcessingEnv re readOnlyTxProcessingEnv.StateProvider, receiptStorage, NullWitnessCollector.Instance, - _blockTree, logManager, new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(readOnlyTxProcessingEnv.StateProvider, logManager))); diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index adc6d14a169..b39559c254e 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -210,10 +210,37 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str { if (!spec.IsEip4844Enabled) { + if (block.Header.DataGasUsed is not null) + { + error = $"A pre-Cancun block cannot have {nameof(block.Header.DataGasUsed)} set."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } + + if (block.Header.ExcessDataGas is not null) + { + error = $"A pre-Cancun block cannot have {nameof(block.Header.ExcessDataGas)} set."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } error = null; return true; } + if (block.Header.DataGasUsed is null) + { + error = $"A post-Cancun block should have {nameof(block.Header.DataGasUsed)} set."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } + + if (block.Header.ExcessDataGas is null) + { + error = $"A post-Cancun block should have {nameof(block.Header.ExcessDataGas)} set."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } + int blobsInBlock = 0; UInt256? dataGasPrice = null; for (int txIndex = block.Transactions.Length - 1; txIndex >= 0; txIndex--) @@ -226,7 +253,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str if (transaction.MaxFeePerDataGas < (dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPrice(block.Header))) { - error = $"A transactions has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; + error = $"A transaction has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; if (_logger.IsWarn) _logger.Warn(error); return false; } @@ -244,7 +271,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str if (dataGasUsed != block.Header.DataGasUsed) { - error = $"DataGasUsed does not match actuall data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; + error = $"DataGasUsed does not match actual data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; if (_logger.IsWarn) _logger.Warn(error); return false; } diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index f8ed5740892..59ab6390e1e 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -323,7 +323,6 @@ protected virtual IBlockProcessor CreateBlockProcessor() => State, ReceiptStorage, NullWitnessCollector.Instance, - BlockTree, LogManager); public async Task WaitForNewHead() diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs deleted file mode 100644 index 3e5e3eef95d..00000000000 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/IParentBlockHeaderFinder.cs +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Nethermind.Core; - -namespace Nethermind.Evm.TransactionProcessing; - -public interface IParentBlockHeaderFinder -{ - BlockHeader? FindParentHeader(BlockHeader block); -} diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index cbc8c754a9b..a8c849563b0 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -353,7 +353,6 @@ protected virtual BlockProcessor CreateBlockProcessor() _api.WorldState, _api.ReceiptStorage, _api.WitnessCollector, - _api.BlockTree, _api.LogManager); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index f44e3a96002..b956aa649f5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -76,7 +76,6 @@ public void Setup() stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, - _blockTree, LimboLogs.Instance); RecoverSignatures txRecovery = new(new EthereumEcdsa(TestBlockchainIds.ChainId, LimboLogs.Instance), NullTxPool.Instance, specProvider, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 542fe92347a..ecde467d8a8 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -67,7 +67,6 @@ public async Task Build(ISpecProvider? specProvider = null, bool isAura = false) Blockchain.ReceiptStorage, dbProvider, Blockchain.SpecProvider, - Blockchain.BlockTree, Blockchain.LogManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index 607ec443887..552fd207632 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -87,7 +87,6 @@ public override IDebugRpcModule Create() _receiptStorage, _dbProvider, _specProvider, - _blockTree, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs index d9ac2edfcb0..adf28739a1c 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofModuleFactory.cs @@ -53,7 +53,7 @@ public override IProofRpcModule Create() _dbProvider, _trieStore, _blockTree, _specProvider, _logManager); ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _blockTree, _logManager); + txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _logManager); Tracer tracer = new( txProcessingEnv.StateProvider, diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs index 15200210018..43d8977a8e2 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceModuleFactory.cs @@ -77,7 +77,6 @@ public override ITraceRpcModule Create() _receiptStorage, _dbProvider, _specProvider, - _blockTree, _logManager, transactionsExecutor); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index 63d056f3ca9..ab2cc12b3e3 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -224,7 +224,6 @@ protected override IBlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, - BlockTree, LogManager); return new TestBlockProcessorInterceptor(processor, _blockProcessingThrottle); diff --git a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs index a8825ba9063..3e6e6b235e0 100644 --- a/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs +++ b/src/Nethermind/Nethermind.Mev.Test/MevRpcModuleTests.TestMevRpcBlockchain.cs @@ -206,7 +206,6 @@ protected override BlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, - BlockTree, LogManager); _tracerFactory = new TracerFactory( diff --git a/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs b/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs index 0e2405e2b58..d09f9f9955c 100644 --- a/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs +++ b/src/Nethermind/Nethermind.Mev/Execution/TracerFactory.cs @@ -49,7 +49,7 @@ public ITracer Create() _dbProvider, _trieStore, _blockTree, _specProvider, _logManager); ReadOnlyChainProcessingEnv chainProcessingEnv = new( - txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _blockTree, _logManager); + txProcessingEnv, Always.Valid, _recoveryStep, NoBlockRewards.Instance, new InMemoryReceiptStorage(), _dbProvider, _specProvider, _logManager); return CreateTracer(txProcessingEnv, chainProcessingEnv); } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index 05dd2db8983..a3ca85cfec9 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -299,7 +299,6 @@ private SyncTestContext CreateSyncManager(int index) stateProvider, receiptStorage, NullWitnessCollector.Instance, - tree, logManager); RecoverSignatures step = new(ecdsa, txPool, specProvider, logManager); @@ -322,7 +321,6 @@ private SyncTestContext CreateSyncManager(int index) devState, receiptStorage, NullWitnessCollector.Instance, - tree, logManager); BlockchainProcessor devChainProcessor = new(tree, devBlockProcessor, step, stateReader, logManager, From 2127d3babffd272a9560bd7e416177cb879a2986 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 15:26:07 +0300 Subject: [PATCH 10/31] Clean up --- src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs | 1 - src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs | 3 --- .../Validators/ContractBasedValidatorTests.cs | 1 - .../Nethermind.Blockchain.Test/BlockProcessorTests.cs | 1 - .../Validators/BlockValidatorTests.cs | 1 - .../Validators/WithdrawalValidatorTests.cs | 1 - src/Nethermind/Nethermind.Blockchain/BlockTree.cs | 1 - src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs | 1 - src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs | 2 -- .../Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs | 1 - .../Nethermind.Consensus/Processing/BlockProcessor.cs | 2 -- .../Processing/ReadOnlyChainProcessingEnv.cs | 1 - .../Nethermind.Consensus/Producers/BlockProducerBase.cs | 3 --- 13 files changed, 19 deletions(-) diff --git a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs index 36cf366fc56..8e3e3a147db 100644 --- a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs @@ -160,7 +160,6 @@ protected async Task RunTest(BlockchainTest test, Stopwatch? stateProvider, receiptStorage, NullWitnessCollector.Instance, - blockTree, _logManager); IBlockchainProcessor blockchainProcessor = new BlockchainProcessor( diff --git a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs index b8a23b6f2f0..fad444b47ce 100644 --- a/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using Nethermind.Blockchain; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -12,7 +11,6 @@ using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.Db; -using Nethermind.Db.Blooms; using Nethermind.Int256; using Nethermind.Evm; using Nethermind.Evm.Tracing; @@ -22,7 +20,6 @@ using Nethermind.Specs.Forks; using Nethermind.Specs.Test; using Nethermind.State; -using Nethermind.State.Repositories; using Nethermind.Trie.Pruning; using NUnit.Framework; diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index 5511d9db936..cd20ec0da8a 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -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; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs index c8ea25143ac..58c6fb51a53 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs @@ -24,7 +24,6 @@ using System.Threading.Tasks; using System.Threading; using FluentAssertions; -using Nethermind.Blockchain.Find; using Nethermind.Consensus.Processing; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Withdrawals; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs index 2ff1e691a19..1993a8fce0f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/BlockValidatorTests.cs @@ -4,7 +4,6 @@ using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; -using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Specs; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs index 881480f3367..97621db36b4 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/WithdrawalValidatorTests.cs @@ -5,7 +5,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Logging; using Nethermind.Specs.Forks; diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 496e084381c..e18069d1d65 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -24,7 +24,6 @@ using Nethermind.Serialization.Rlp; using Nethermind.State.Repositories; using Nethermind.Db.Blooms; -using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Blockchain { diff --git a/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs b/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs index 6c31423670d..9d31f61337c 100644 --- a/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs +++ b/src/Nethermind/Nethermind.Blockchain/Find/IBlockFinder.cs @@ -4,7 +4,6 @@ using System; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm.TransactionProcessing; namespace Nethermind.Blockchain.Find { diff --git a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs index f7dc98ecea0..09a5478791a 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReadOnlyBlockTree.cs @@ -6,11 +6,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Visitors; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; namespace Nethermind.Blockchain diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs index da8b503dd32..ddc5c402b11 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Concurrent; using System.Linq; -using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Db; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index bf52a322557..d49889a68c5 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Numerics; using Nethermind.Blockchain; -using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; @@ -247,7 +246,6 @@ protected virtual TxReceipt[] ProcessBlock( _stateProvider.Commit(spec); _stateProvider.RecalculateStateRoot(); - block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = block.Header.CalculateHash(); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs index acb585b4d72..da38938699c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index bf02f7ebba0..05113fb8558 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; @@ -13,7 +11,6 @@ using Nethermind.Consensus.Transactions; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Evm; using Nethermind.Evm.Tracing; From 4548a9fb1da3e9d3d676ee7a9127fa063a7af06f Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 16:54:29 +0300 Subject: [PATCH 11/31] Clean up checks --- .../Validators/BlockValidator.cs | 27 ------------------- .../Validators/HeaderValidator.cs | 24 ++++++++--------- 2 files changed, 12 insertions(+), 39 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index b39559c254e..4b2fe6a3758 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -210,37 +210,10 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str { if (!spec.IsEip4844Enabled) { - if (block.Header.DataGasUsed is not null) - { - error = $"A pre-Cancun block cannot have {nameof(block.Header.DataGasUsed)} set."; - if (_logger.IsWarn) _logger.Warn(error); - return false; - } - - if (block.Header.ExcessDataGas is not null) - { - error = $"A pre-Cancun block cannot have {nameof(block.Header.ExcessDataGas)} set."; - if (_logger.IsWarn) _logger.Warn(error); - return false; - } error = null; return true; } - if (block.Header.DataGasUsed is null) - { - error = $"A post-Cancun block should have {nameof(block.Header.DataGasUsed)} set."; - if (_logger.IsWarn) _logger.Warn(error); - return false; - } - - if (block.Header.ExcessDataGas is null) - { - error = $"A post-Cancun block should have {nameof(block.Header.ExcessDataGas)} set."; - if (_logger.IsWarn) _logger.Warn(error); - return false; - } - int blobsInBlock = 0; UInt256? dataGasPrice = null; for (int txIndex = block.Transactions.Length - 1; txIndex >= 0; txIndex--) diff --git a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs index d06440ae66c..060454d357e 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs @@ -281,18 +281,6 @@ header.Bloom is not null && private bool ValidateDataGasFields(BlockHeader header, BlockHeader parentHeader, IReleaseSpec spec) { - if (spec.IsEip4844Enabled && header.DataGasUsed is null) - { - if (_logger.IsWarn) _logger.Warn($"DataGasUsed field is not set."); - return false; - } - - if (spec.IsEip4844Enabled && header.ExcessDataGas is null) - { - if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is not set."); - return false; - } - if (!spec.IsEip4844Enabled) { if (header.DataGasUsed is not null) @@ -310,6 +298,18 @@ private bool ValidateDataGasFields(BlockHeader header, BlockHeader parentHeader, return true; } + if (header.DataGasUsed is null) + { + if (_logger.IsWarn) _logger.Warn($"DataGasUsed field is not set."); + return false; + } + + if (header.ExcessDataGas is null) + { + if (_logger.IsWarn) _logger.Warn($"ExcessDataGas field is not set."); + return false; + } + UInt256? expectedExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parentHeader, spec); if (header.ExcessDataGas != expectedExcessDataGas) From d86ec23080a8ebb88bbe8a9477226322cba34b86 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 17:17:17 +0300 Subject: [PATCH 12/31] Fix tests --- .../Validators/ShardBlobBlockValidatorTests.cs | 6 +++++- .../Nethermind.Core.Test/Builders/BlockBuilder.cs | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs index cc7f1082614..ad361daadea 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/ShardBlobBlockValidatorTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using Nethermind.Blockchain.Find; using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Specs; @@ -10,6 +11,7 @@ using Nethermind.Logging; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Validators; @@ -20,12 +22,14 @@ public class ShardBlobBlockValidatorTests public static bool Data_gas_fields_should_be_set(IReleaseSpec spec, ulong? dataGasUsed, ulong? excessDataGas) { ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec)); - BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, TestLogManager.Instance); + HeaderValidator headerValidator = new(Substitute.For(), 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); } diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs index 445553e93d7..c26ac138b54 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockBuilder.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; using System.Linq; using Nethermind.Core.Crypto; @@ -165,6 +166,7 @@ public BlockBuilder WithParent(BlockHeader blockHeader) TestObjectInternal.Header.Number = blockHeader?.Number + 1 ?? 0; TestObjectInternal.Header.Timestamp = blockHeader?.Timestamp + 1 ?? 0; TestObjectInternal.Header.ParentHash = blockHeader is null ? Keccak.Zero : blockHeader.Hash; + TestObjectInternal.Header.MaybeParent = blockHeader is null ? null : new WeakReference(blockHeader); return this; } From a132a10c05f8415ef3595d0c6c596df82f5dfacd Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 19:50:30 +0300 Subject: [PATCH 13/31] Fix header mapping to rpc --- .../EngineModuleTests.V3.cs | 6 ++++-- .../Nethermind.Merge.Plugin/Data/ExecutionPayload.cs | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index dd25c68e9e5..8954f6d6536 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -59,8 +59,10 @@ public async Task GetPayloadV3_should_fail_on_unknown_payload() public async Task PayloadV3_should_return_all_the_blobs(int blobTxCount) { (IEngineRpcModule rpcModule, string payloadId) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); - BlobsBundleV1 getPayloadResultBlobsBundle = - (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.BlobsBundle!; + var result = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); + BlobsBundleV1 getPayloadResultBlobsBundle = result.Data!.BlobsBundle!; + Assert.That(result.Data.ExecutionPayload.DataGasUsed, Is.Not.Null); + Assert.That(result.Data.ExecutionPayload.ExcessDataGas, Is.Not.Null); Assert.That(getPayloadResultBlobsBundle.Blobs!.Length, Is.EqualTo(blobTxCount)); Assert.That(getPayloadResultBlobsBundle.Commitments!.Length, Is.EqualTo(blobTxCount)); Assert.That(getPayloadResultBlobsBundle.Proofs!.Length, Is.EqualTo(blobTxCount)); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs index feb086c0d7d..fc75a7cf6fc 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs @@ -39,6 +39,7 @@ public ExecutionPayload(Block block) Timestamp = block.Timestamp; BaseFeePerGas = block.BaseFeePerGas; Withdrawals = block.Withdrawals; + DataGasUsed = block.DataGasUsed; ExcessDataGas = block.ExcessDataGas; SetTransactions(block.Transactions); @@ -94,18 +95,19 @@ public byte[][] Transactions public IEnumerable? Withdrawals { get; set; } /// - /// Gets or sets as defined in + /// Gets or sets as defined in /// EIP-4844. /// [JsonProperty(ItemConverterType = typeof(NullableUInt256Converter), NullValueHandling = NullValueHandling.Ignore)] - public ulong? ExcessDataGas { get; set; } + public ulong? DataGasUsed { get; set; } /// - /// Gets or sets as defined in + /// Gets or sets as defined in /// EIP-4844. /// [JsonProperty(ItemConverterType = typeof(NullableUInt256Converter), NullValueHandling = NullValueHandling.Ignore)] - public ulong? DataGasUsed { get; set; } + public ulong? ExcessDataGas { get; set; } + /// /// Creates the execution block from payload. From 25b56af3381e0155fdae5d3aaaa86e549efe560e Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 20:22:48 +0300 Subject: [PATCH 14/31] Fix data gas calculations --- .../Nethermind.Consensus/Processing/BlockProcessor.cs | 11 +++-------- .../EngineModuleTests.V3.cs | 3 ++- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index d49889a68c5..625264573c2 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -225,19 +225,14 @@ protected virtual TxReceipt[] ProcessBlock( _receiptsTracer.SetOtherTracer(blockTracer); _receiptsTracer.StartNewBlockTrace(block); - if (spec.IsEip4844Enabled && block.Header.Number != 0) + TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, _receiptsTracer, spec); + + if (spec.IsEip4844Enabled) { block.Header.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas( block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); - - if (block.Header.ExcessDataGas is null) - { - throw new ApplicationException("ExcessDataGas cannot be null"); - } } - TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, _receiptsTracer, spec); - block.Header.ReceiptsRoot = receipts.GetReceiptsRoot(spec, block.ReceiptsRoot); ApplyMinerRewards(block, blockTracer, spec); _withdrawalProcessor.ProcessWithdrawals(block, spec); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index 8954f6d6536..31085f61eb2 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -13,6 +13,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.JsonRpc; using Nethermind.Logging; using Nethermind.Merge.Plugin.Data; @@ -61,7 +62,7 @@ public async Task PayloadV3_should_return_all_the_blobs(int blobTxCount) (IEngineRpcModule rpcModule, string payloadId) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); var result = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); BlobsBundleV1 getPayloadResultBlobsBundle = result.Data!.BlobsBundle!; - Assert.That(result.Data.ExecutionPayload.DataGasUsed, Is.Not.Null); + Assert.That(result.Data.ExecutionPayload.DataGasUsed, Is.EqualTo(IntrinsicGasCalculator.CalculateDataGas(blobTxCount))); Assert.That(result.Data.ExecutionPayload.ExcessDataGas, Is.Not.Null); Assert.That(getPayloadResultBlobsBundle.Blobs!.Length, Is.EqualTo(blobTxCount)); Assert.That(getPayloadResultBlobsBundle.Commitments!.Length, Is.EqualTo(blobTxCount)); From f0a5e4cd23ad945afe8b04763167801c6bab3a6b Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 21:29:33 +0300 Subject: [PATCH 15/31] Add safety checks --- .../Producers/BlockProducerBase.cs | 9 ++++++++- .../BlockProduction/PostMergeBlockProducer.cs | 14 +++++++++++--- .../ChainSpecStyle/Json/ChainSpecGenesisJson.cs | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index 05113fb8558..5710c850565 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -299,8 +299,15 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, header.TotalDifficulty = parent.TotalDifficulty + difficulty; if (Logger.IsDebug) Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}."); + + IReleaseSpec spec = _specProvider.GetSpec(header); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); - header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetSpec(header)); + + if (spec.IsEip4844Enabled) + { + header.DataGasUsed = 0; + header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, spec); + } return header; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs index eebd64ff0c3..37a35a2f65d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs @@ -16,6 +16,7 @@ using System.Threading; using Nethermind.Logging; using Nethermind.State; +using Nethermind.Evm; namespace Nethermind.Merge.Plugin.BlockProduction { @@ -79,22 +80,29 @@ public virtual Block PrepareEmptyBlock(BlockHeader parent, PayloadAttributes? pa protected override Block PrepareBlock(BlockHeader parent, PayloadAttributes? payloadAttributes = null) { Block block = base.PrepareBlock(parent, payloadAttributes); - AmendHeader(block.Header); + AmendHeader(block.Header, parent); return block; } protected override BlockHeader PrepareBlockHeader(BlockHeader parent, PayloadAttributes? payloadAttributes = null) { BlockHeader blockHeader = base.PrepareBlockHeader(parent, payloadAttributes); - AmendHeader(blockHeader); + AmendHeader(blockHeader, parent); return blockHeader; } // TODO: this seems to me that it should be done in the Eth2 seal engine? - private void AmendHeader(BlockHeader blockHeader) + private void AmendHeader(BlockHeader blockHeader, BlockHeader parent) { blockHeader.ExtraData = _blocksConfig.GetExtraDataBytes(); blockHeader.IsPostMerge = true; + IReleaseSpec spec = _specProvider.GetSpec(blockHeader); + + if (spec.IsEip4844Enabled) + { + blockHeader.DataGasUsed = 0; + blockHeader.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, spec); + } } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs index e44df546b35..36b80f2e38d 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs @@ -23,7 +23,7 @@ internal class ChainSpecGenesisJson public Keccak StateRoot { get; set; } - public ulong? ExcessDataGas { get; set; } public ulong? DataGasUsed { get; set; } + public ulong? ExcessDataGas { get; set; } } } From 4fc22f13ce05e0dedecc848f1b6052544f448879 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 5 Jun 2023 23:21:44 +0300 Subject: [PATCH 16/31] Fix and improve --- .../Nethermind.Consensus/Validators/BlockValidator.cs | 2 +- src/Nethermind/Nethermind.Core/Transaction.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 4b2fe6a3758..e02a2269ed0 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -224,7 +224,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str continue; } - if (transaction.MaxFeePerDataGas < (dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPrice(block.Header))) + if (transaction.MaxFeePerDataGas < (dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPricePerUnit(block.Header))) { error = $"A transaction has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; if (_logger.IsWarn) _logger.Warn(error); diff --git a/src/Nethermind/Nethermind.Core/Transaction.cs b/src/Nethermind/Nethermind.Core/Transaction.cs index ca3e57ce5cb..2acea9cc206 100644 --- a/src/Nethermind/Nethermind.Core/Transaction.cs +++ b/src/Nethermind/Nethermind.Core/Transaction.cs @@ -173,7 +173,8 @@ public string ToString(string indent) if (SupportsBlobs) { - builder.AppendLine($"{indent}BlobVersionedHashes: {BlobVersionedHashes?.Length}"); + builder.AppendLine($"{indent}{nameof(MaxFeePerDataGas)}: {MaxFeePerDataGas}"); + builder.AppendLine($"{indent}{nameof(BlobVersionedHashes)}: {BlobVersionedHashes?.Length}"); } return builder.ToString(); From 3e6253d9a657338c16beccd6d5626b675914d4a4 Mon Sep 17 00:00:00 2001 From: Nikita Mescheryakov Date: Tue, 6 Jun 2023 17:52:45 +0900 Subject: [PATCH 17/31] Blob gas info in receipts (#5767) * Blob gas info in receipts * Fix gas price * Fix spaces * Add tests * Supports blobs * Ignore on null * Fix suggestions * Fix build --------- Co-authored-by: Nikita Mescheryakov --- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 7 ++- .../Nethermind.Evm/TransactionExtensions.cs | 35 +++++++++++++++ .../BlockchainBridgeTests.cs | 45 ++++++++++++++----- .../Nethermind.Facade.Test.csproj | 1 + .../Nethermind.Facade/BlockchainBridge.cs | 9 ++-- .../Nethermind.Facade/IBlockchainBridge.cs | 5 ++- .../Data/ReceiptsForRpcTests.cs | 2 +- .../Modules/Eth/EthRpcModuleTests.cs | 18 +++++--- .../Converters/TxReceiptConverter.cs | 2 +- .../Nethermind.JsonRpc/Data/ReceiptForRpc.cs | 12 +++-- .../Modules/Eth/EthRpcModule.cs | 7 +-- .../Modules/Parity/ParityRpcModule.cs | 6 ++- .../Modules/Proof/ProofRpcModule.cs | 7 ++- 13 files changed, 116 insertions(+), 40 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index 08e46ad6ee0..631d182503b 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -96,11 +96,14 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release public static ulong CalculateDataGas(int blobCount) => (ulong)blobCount * Eip4844Constants.DataGasPerBlob; + public static ulong CalculateDataGas(Transaction transaction) => + CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); + public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => - CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0) * CalculateDataGasPricePerUnit(header); + CalculateDataGas(transaction) * CalculateDataGasPricePerUnit(header); public static UInt256 CalculateDataGasPrice(BlockHeader header) => - header.DataGasUsed.Value * CalculateDataGasPricePerUnit(header); + header.DataGasUsed!.Value * CalculateDataGasPricePerUnit(header); public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) { diff --git a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs index a5f85fe7075..e0bd18c1860 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs @@ -14,5 +14,40 @@ tx.To is not null : tx.IsSystem() ? tx.SenderAddress : ContractAddress.From(tx.SenderAddress, nonce > 0 ? nonce - 1 : nonce); + + public static TxGasInfo GetGasInfo(this Transaction tx, bool is1559Enabled, BlockHeader header) + { + UInt256 effectiveGasPrice = tx.CalculateEffectiveGasPrice(is1559Enabled, header.BaseFeePerGas); + ulong? dataGas = null; + UInt256? dataGasPrice = null; + if (tx.SupportsBlobs) + { + dataGas = IntrinsicGasCalculator.CalculateDataGas(tx); + dataGasPrice = IntrinsicGasCalculator.CalculateDataGasPrice(header, tx); + } + + return new(effectiveGasPrice, dataGasPrice, dataGas); + } + } + + public struct TxGasInfo + { + public TxGasInfo() { } + + public TxGasInfo(UInt256? effectiveGasPrice, UInt256? dataGasPrice, ulong? dataGasUsed) + { + EffectiveGasPrice = effectiveGasPrice; + DataGasPrice = dataGasPrice; + DataGasUsed = dataGasUsed; + } + + public TxGasInfo(UInt256? effectiveGasPrice) + { + EffectiveGasPrice = effectiveGasPrice; + } + + public UInt256? EffectiveGasPrice { get; private set; } + public UInt256? DataGasPrice { get; private set; } + public ulong? DataGasUsed { get; private set; } } } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 6ace9a200d0..4dba1905c19 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -28,6 +28,7 @@ using NSubstitute; using NUnit.Framework; using Nethermind.Config; +using Nethermind.Evm; namespace Nethermind.Facade.Test { @@ -231,20 +232,34 @@ public void Bridge_head_is_correct(long headNumber) _blockchainBridge.HeadBlock.Should().Be(head); } - [TestCase(true)] - [TestCase(false)] - public void GetReceiptAndEffectiveGasPrice_returns_correct_results(bool isCanonical) + [TestCase(true, true)] + [TestCase(false, true)] + [TestCase(true, false)] + [TestCase(false, false)] + public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool postEip4844) { Keccak txHash = TestItem.KeccakA; Keccak blockHash = TestItem.KeccakB; UInt256 effectiveGasPrice = 123; - Transaction tx = Build.A.Transaction - .WithGasPrice(effectiveGasPrice) - .TestObject; - Block block = Build.A.Block - .WithTransactions(tx) - .TestObject; + Transaction tx = postEip4844 + ? Build.A.Transaction + .WithGasPrice(effectiveGasPrice) + .WithType(TxType.Blob) + .WithMaxFeePerDataGas(2) + .WithBlobVersionedHashes(2) + .TestObject + : Build.A.Transaction + .WithGasPrice(effectiveGasPrice) + .TestObject; + Block block = postEip4844 + ? Build.A.Block + .WithTransactions(tx) + .WithExcessDataGas(2) + .TestObject + : Build.A.Block + .WithTransactions(tx) + .TestObject; TxReceipt receipt = Build.A.Receipt .WithBlockHash(blockHash) .WithTransactionHash(txHash) @@ -255,8 +270,16 @@ public void GetReceiptAndEffectiveGasPrice_returns_correct_results(bool isCanoni _receiptStorage.FindBlockHash(txHash).Returns(blockHash); _receiptStorage.Get(block).Returns(new[] { receipt }); - (TxReceipt Receipt, UInt256? EffectiveGasPrice, int LogIndexStart) result = isCanonical ? (receipt, effectiveGasPrice, 0) : (null, null, 0); - _blockchainBridge.GetReceiptAndEffectiveGasPrice(txHash).Should().BeEquivalentTo(result); + (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) result = postEip4844 + ? (receipt, new(effectiveGasPrice, 262144, 262144), 0) + : (receipt, new(effectiveGasPrice), 0); + + if (!isCanonical) + { + result = (null, null, 0); + } + + _blockchainBridge.GetReceiptAndGasInfo(txHash).Should().BeEquivalentTo(result); } } } diff --git a/src/Nethermind/Nethermind.Facade.Test/Nethermind.Facade.Test.csproj b/src/Nethermind/Nethermind.Facade.Test/Nethermind.Facade.Test.csproj index 15608eea2e8..5feafc0ae10 100644 --- a/src/Nethermind/Nethermind.Facade.Test/Nethermind.Facade.Test.csproj +++ b/src/Nethermind/Nethermind.Facade.Test/Nethermind.Facade.Test.csproj @@ -3,6 +3,7 @@ net7.0 true + annotations diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 0746848502a..dbc10993fb9 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -83,7 +83,7 @@ public Block? HeadBlock public bool IsMining { get; } - public (TxReceipt Receipt, UInt256? EffectiveGasPrice, int LogIndexStart) GetReceiptAndEffectiveGasPrice(Keccak txHash) + public (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) GetReceiptAndGasInfo(Keccak txHash) { Keccak blockHash = _receiptFinder.FindBlockHash(txHash); if (blockHash is not null) @@ -96,15 +96,14 @@ public Block? HeadBlock int logIndexStart = txReceipts.GetBlockLogFirstIndex(txReceipt.Index); Transaction tx = block.Transactions[txReceipt.Index]; bool is1559Enabled = _specProvider.GetSpecFor1559(block.Number).IsEip1559Enabled; - UInt256 effectiveGasPrice = tx.CalculateEffectiveGasPrice(is1559Enabled, block.Header.BaseFeePerGas); - return (txReceipt, effectiveGasPrice, logIndexStart); + return (txReceipt, tx.GetGasInfo(is1559Enabled, block.Header), logIndexStart); } } return (null, null, 0); } - public (TxReceipt Receipt, Transaction Transaction, UInt256? baseFee) GetTransaction(Keccak txHash) + public (TxReceipt? Receipt, Transaction Transaction, UInt256? baseFee) GetTransaction(Keccak txHash) { Keccak blockHash = _receiptFinder.FindBlockHash(txHash); if (blockHash is not null) @@ -271,7 +270,7 @@ private void CallAndRestore( if (releaseSpec.IsEip4844Enabled) { - callHeader.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); + callHeader.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas(transaction); callHeader.ExcessDataGas = treatBlockHeaderAsParentBlock ? IntrinsicGasCalculator.CalculateExcessDataGas(blockHeader, releaseSpec) : blockHeader.ExcessDataGas; diff --git a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs index 0b39fac85b9..cccff0b75ea 100644 --- a/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs @@ -7,6 +7,7 @@ using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Facade.Filters; using Nethermind.Int256; using Nethermind.Trie; @@ -21,8 +22,8 @@ public interface IBlockchainBridge : ILogFinder void RecoverTxSenders(Block block); Address? RecoverTxSender(Transaction tx); TxReceipt GetReceipt(Keccak txHash); - (TxReceipt Receipt, UInt256? EffectiveGasPrice, int LogIndexStart) GetReceiptAndEffectiveGasPrice(Keccak txHash); - (TxReceipt Receipt, Transaction Transaction, UInt256? baseFee) GetTransaction(Keccak txHash); + (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) GetReceiptAndGasInfo(Keccak txHash); + (TxReceipt? Receipt, Transaction Transaction, UInt256? baseFee) GetTransaction(Keccak txHash); BlockchainBridge.CallOutput Call(BlockHeader header, Transaction tx, CancellationToken cancellationToken); BlockchainBridge.CallOutput EstimateGas(BlockHeader header, Transaction tx, CancellationToken cancellationToken); BlockchainBridge.CallOutput CreateAccessList(BlockHeader header, Transaction tx, CancellationToken cancellationToken, bool optimize); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/ReceiptsForRpcTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/ReceiptsForRpcTests.cs index 06e71db2bf5..2ab81efce34 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/ReceiptsForRpcTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/ReceiptsForRpcTests.cs @@ -38,7 +38,7 @@ public void Are_log_indexes_unique() }; UInt256 effectiveGasPrice = new(5526); - ReceiptForRpc receiptForRpc = new(txHash, receipt1, effectiveGasPrice); + ReceiptForRpc receiptForRpc = new(txHash, receipt1, new(effectiveGasPrice)); long?[] indexes = receiptForRpc.Logs.Select(log => log.LogIndex).ToArray(); long?[] expected = { 0, 1, 2 }; diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 36a6105b6b8..4f97badc663 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -818,8 +818,9 @@ public async Task Eth_get_block_by_number_with_recovering_sender_from_receipts() Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x1\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x221\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[{\"nonce\":\"0x0\",\"blockHash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"blockNumber\":\"0x1\",\"transactionIndex\":\"0x0\",\"from\":\"0x2d36e6c27c34ea22620e7b7c45de774599406cf3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\"}],\"transactionsRoot\":\"0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5\",\"uncles\":[]},\"id\":67}")); } - [Test] - public async Task Eth_get_transaction_receipt() + [TestCase(false)] + [TestCase(true)] + public async Task Eth_get_transaction_receipt(bool postEip4844) { using Context ctx = await Context.Create(); IBlockchainBridge blockchainBridge = Substitute.For(); @@ -840,7 +841,9 @@ public async Task Eth_get_transaction_receipt() .WithLogs(entries).TestObject; TxReceipt[] receiptsTab = { receipt }; - blockchainBridge.GetReceiptAndEffectiveGasPrice(Arg.Any()).Returns((receipt, UInt256.One, 0)); + + blockchainBridge.GetReceiptAndGasInfo(Arg.Any()) + .Returns((receipt, postEip4844 ? new(UInt256.One, 2, 3) : new(UInt256.One), 0)); blockFinder.FindBlock(Arg.Any()).Returns(block); receiptFinder.Get(Arg.Any()).Returns(receiptsTab); receiptFinder.Get(Arg.Any()).Returns(receiptsTab); @@ -848,7 +851,10 @@ public async Task Eth_get_transaction_receipt() ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).WithBlockchainBridge(blockchainBridge).Build(); string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString()); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); + if (postEip4844) + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"dataGasUsed\":\"0x3\",\"dataGasPrice\":\"0x2\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); + else + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}")); } @@ -903,7 +909,7 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts() Logs = logEntries }; - blockchainBridge.GetReceiptAndEffectiveGasPrice(Arg.Any()).Returns((receipt2, UInt256.One, 2)); + blockchainBridge.GetReceiptAndGasInfo(Arg.Any()).Returns((receipt2, new(UInt256.One), 2)); TxReceipt[] receipts = { receipt1, receipt2 }; @@ -959,7 +965,7 @@ public async Task Eth_getTransactionReceipt_return_info_about_mined_tx() blockFinder.FindBlock(Arg.Any()).Returns(block); receiptFinder.Get(Arg.Any()).Returns(receiptsTab); receiptFinder.Get(Arg.Any()).Returns(receiptsTab); - blockchainBridge.GetReceiptAndEffectiveGasPrice(Arg.Any()).Returns((receipt, UInt256.One, 0)); + blockchainBridge.GetReceiptAndGasInfo(Arg.Any()).Returns((receipt, new(UInt256.One), 0)); ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).WithBlockchainBridge(blockchainBridge).Build(); string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString()); diff --git a/src/Nethermind/Nethermind.JsonRpc/Converters/TxReceiptConverter.cs b/src/Nethermind/Nethermind.JsonRpc/Converters/TxReceiptConverter.cs index 682247df55b..34da8afada2 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Converters/TxReceiptConverter.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Converters/TxReceiptConverter.cs @@ -13,7 +13,7 @@ public class TxReceiptConverter : JsonConverter { public override void WriteJson(JsonWriter writer, TxReceipt value, JsonSerializer serializer) { - serializer.Serialize(writer, new ReceiptForRpc(value.TxHash!, value, UInt256.Zero)); + serializer.Serialize(writer, new ReceiptForRpc(value.TxHash!, value, new(UInt256.Zero))); } public override TxReceipt ReadJson(JsonReader reader, Type objectType, TxReceipt existingValue, bool hasExistingValue, JsonSerializer serializer) diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs index 00de50c6f1b..7ce43ff3411 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs @@ -1,10 +1,10 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Evm; using Nethermind.Int256; using Newtonsoft.Json; @@ -16,7 +16,7 @@ public ReceiptForRpc() { } - public ReceiptForRpc(Keccak txHash, TxReceipt receipt, UInt256? effectiveGasPrice, int logIndexStart = 0) + public ReceiptForRpc(Keccak txHash, TxReceipt receipt, TxGasInfo gasInfo, int logIndexStart = 0) { TransactionHash = txHash; TransactionIndex = receipt.Index; @@ -24,7 +24,9 @@ public ReceiptForRpc(Keccak txHash, TxReceipt receipt, UInt256? effectiveGasPric BlockNumber = receipt.BlockNumber; CumulativeGasUsed = receipt.GasUsedTotal; GasUsed = receipt.GasUsed; - EffectiveGasPrice = effectiveGasPrice; + EffectiveGasPrice = gasInfo.EffectiveGasPrice; + DataGasUsed = gasInfo.DataGasUsed; + DataGasPrice = gasInfo.DataGasPrice; From = receipt.Sender; To = receipt.Recipient; ContractAddress = receipt.ContractAddress; @@ -42,6 +44,10 @@ public ReceiptForRpc(Keccak txHash, TxReceipt receipt, UInt256? effectiveGasPric public long BlockNumber { get; set; } public long CumulativeGasUsed { get; set; } public long GasUsed { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? DataGasUsed { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public UInt256? DataGasPrice { get; set; } public UInt256? EffectiveGasPrice { get; set; } public Address From { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index 743f656c121..2fb9ce4c21a 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -15,6 +15,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Facade; using Nethermind.Facade.Eth; using Nethermind.Facade.Filters; @@ -494,14 +495,14 @@ public ResultWrapper eth_getTransactionByBlockNumberAndIndex( public Task> eth_getTransactionReceipt(Keccak txHash) { - (TxReceipt receipt, UInt256? effectiveGasPrice, int logIndexStart) = _blockchainBridge.GetReceiptAndEffectiveGasPrice(txHash); - if (receipt is null) + (TxReceipt? receipt, TxGasInfo? gasInfo, int logIndexStart) = _blockchainBridge.GetReceiptAndGasInfo(txHash); + if (receipt is null || gasInfo is null) { return Task.FromResult(ResultWrapper.Success(null)); } if (_logger.IsTrace) _logger.Trace($"eth_getTransactionReceipt request {txHash}, result: {txHash}"); - return Task.FromResult(ResultWrapper.Success(new(txHash, receipt, effectiveGasPrice, logIndexStart))); + return Task.FromResult(ResultWrapper.Success(new(txHash, receipt, gasInfo.Value, logIndexStart))); } public ResultWrapper eth_getUncleByBlockHashAndIndex(Keccak blockHash, UInt256 positionIndex) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityRpcModule.cs index 07680e96e90..7e0b3a92a38 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityRpcModule.cs @@ -11,7 +11,7 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Crypto; -using Nethermind.Int256; +using Nethermind.Evm; using Nethermind.JsonRpc.Data; using Nethermind.KeyStore; using Nethermind.Serialization.Rlp; @@ -77,7 +77,9 @@ public ResultWrapper parity_getBlockReceipts(BlockParameter blo bool isEip1559Enabled = _specProvider.GetSpec(block.Header).IsEip1559Enabled; IEnumerable result = receipts .Zip(block.Transactions, (r, t) => - new ReceiptForRpc(t.Hash, r, t.CalculateEffectiveGasPrice(isEip1559Enabled, block.BaseFeePerGas), receipts.GetBlockLogFirstIndex(r.Index))); + { + return new ReceiptForRpc(t.Hash, r, t.GetGasInfo(isEip1559Enabled, block.Header), receipts.GetBlockLogFirstIndex(r.Index)); + }); ReceiptForRpc[] resultAsArray = result.ToArray(); return ResultWrapper.Success(resultAsArray); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs index 05427d8a01b..0ead70e46c1 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Proof/ProofRpcModule.cs @@ -4,18 +4,16 @@ using System; using System.Collections.Generic; using System.Linq; -using Nethermind.Blockchain; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Tracing; using Nethermind.Core; using Nethermind.Core.Crypto; -using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.Proofs; -using Nethermind.Facade; using Nethermind.JsonRpc.Data; using Nethermind.Logging; using Nethermind.Serialization.Rlp; @@ -159,7 +157,8 @@ public ResultWrapper proof_getTransactionReceipt(Keccak txHash Transaction? tx = txs.FirstOrDefault(x => x.Hash == txHash); int logIndexStart = _receiptFinder.Get(block).GetBlockLogFirstIndex(receipt.Index); - receiptWithProof.Receipt = new ReceiptForRpc(txHash, receipt, tx?.CalculateEffectiveGasPrice(isEip1559Enabled, block.BaseFeePerGas), logIndexStart); + + receiptWithProof.Receipt = new ReceiptForRpc(txHash, receipt, tx?.GetGasInfo(isEip1559Enabled, block.Header) ?? new(), logIndexStart); receiptWithProof.ReceiptProof = BuildReceiptProofs(block.Header, receipts, receipt.Index); receiptWithProof.TxProof = BuildTxProofs(txs, _specProvider.GetSpec(block.Header), receipt.Index); From 14e9ce2e820f300de76abf901d7064b9e18b36e4 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Fri, 9 Jun 2023 11:02:17 +0300 Subject: [PATCH 18/31] Increase data gas limits --- .../Encoding/HeaderDecoderTests.cs | 52 +++++++++---------- .../Nethermind.Core/Eip4844Constants.cs | 7 ++- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 7 +-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs index 78ddaf49f05..eb6b1be1130 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/HeaderDecoderTests.cs @@ -128,32 +128,6 @@ public void If_withdrawals_are_null_should_not_encode() Convert.ToHexString(rlp.Bytes).ToLower().Should().Be("f901f7a0ff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008080833d090080830f424083010203a02ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e288000000000000000001"); } - [TestCaseSource(nameof(ExcessDataGasCaseSource))] - public void Can_encode_decode_with_excessDataGas(ulong? dataGasUsed, ulong? excessDataGas) - { - BlockHeader header = Build.A.BlockHeader - .WithTimestamp(ulong.MaxValue) - .WithBaseFee(1) - .WithWithdrawalsRoot(Keccak.Zero) - .WithDataGasUsed(dataGasUsed) - .WithExcessDataGas(excessDataGas).TestObject; - - Rlp rlp = Rlp.Encode(header); - BlockHeader blockHeader = Rlp.Decode(rlp.Bytes.AsSpan()); - - blockHeader.DataGasUsed.Should().Be(dataGasUsed); - blockHeader.ExcessDataGas.Should().Be(excessDataGas); - } - - public static IEnumerable ExcessDataGasCaseSource() - { - yield return new object[] { null, null }; - yield return new object[] { 0ul, 0ul }; - yield return new object[] { 1ul, 2ul }; - yield return new object[] { ulong.MaxValue / 2, ulong.MaxValue }; - yield return new object[] { ulong.MaxValue, ulong.MaxValue / 2 }; - } - [TestCase(-1)] [TestCase(long.MinValue)] public void Can_encode_decode_with_negative_long_fields(long negativeLong) @@ -187,4 +161,30 @@ public void Can_encode_decode_with_negative_long_when_using_span(long negativeLo blockHeader.Number.Should().Be(negativeLong); blockHeader.GasLimit.Should().Be(negativeLong); } + + [TestCaseSource(nameof(ExcessDataGasCaseSource))] + public void Can_encode_decode_with_excessDataGas(ulong? dataGasUsed, ulong? excessDataGas) + { + BlockHeader header = Build.A.BlockHeader + .WithTimestamp(ulong.MaxValue) + .WithBaseFee(1) + .WithWithdrawalsRoot(Keccak.Zero) + .WithDataGasUsed(dataGasUsed) + .WithExcessDataGas(excessDataGas).TestObject; + + Rlp rlp = Rlp.Encode(header); + BlockHeader blockHeader = Rlp.Decode(rlp.Bytes.AsSpan()); + + blockHeader.DataGasUsed.Should().Be(dataGasUsed); + blockHeader.ExcessDataGas.Should().Be(excessDataGas); + } + + public static IEnumerable ExcessDataGasCaseSource() + { + yield return new object?[] { null, null }; + yield return new object?[] { 0ul, 0ul }; + yield return new object?[] { 1ul, 2ul }; + yield return new object?[] { ulong.MaxValue / 2, ulong.MaxValue }; + yield return new object?[] { ulong.MaxValue, ulong.MaxValue / 2 }; + } } diff --git a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs index c631ee943f8..926a5bc5d6e 100644 --- a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs @@ -11,7 +11,10 @@ public class Eip4844Constants public const int MinBlobsPerTransaction = 1; public const ulong DataGasPerBlob = 1 << 17; - public const ulong TargetDataGasPerBlock = 1 << 18; - public const ulong MaxDataGasPerBlock = 1 << 19; + public const ulong TargetDataGasPerBlock = DataGasPerBlob * 3; + public const ulong MaxDataGasPerBlock = DataGasPerBlob * 6; public const ulong MaxDataGasPerTransaction = MaxDataGasPerBlock; + + public static readonly UInt256 DataGasUpdateFraction = 3338477; + public static readonly UInt256 MinDataGasPrice = 1; } diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index 631d182503b..2f8d1afe11f 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -117,10 +117,7 @@ public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) { - UInt256 dataGasPriceUpdateFraction = 2225652; - UInt256 minDataGasPrice = 1L; - - UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) + static UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) { UInt256 output = UInt256.Zero; @@ -137,7 +134,7 @@ UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) } UInt256 scaleDueToParentExcessDataGas = - FakeExponential(minDataGasPrice, excessDataGas, dataGasPriceUpdateFraction); + FakeExponential(Eip4844Constants.MinDataGasPrice, excessDataGas, Eip4844Constants.DataGasUpdateFraction); return scaleDueToParentExcessDataGas; } From 7c61b539edec68388c7ba04ed7193b81636dcb31 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Fri, 9 Jun 2023 13:20:50 +0300 Subject: [PATCH 19/31] Clean up --- .../Receipts/InMemoryReceiptStorage.cs | 1 + .../Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs | 2 ++ .../Producers/BlockProducerBase.cs | 6 ------ .../Nethermind.Consensus/Producers/TxPoolTxSource.cs | 2 ++ .../Nethermind.Consensus/Validators/BlockValidator.cs | 2 +- src/Nethermind/Nethermind.Core/BlockHeader.cs | 2 +- src/Nethermind/Nethermind.Core/Eip4844Constants.cs | 7 +++---- .../Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs | 4 ++-- .../Nethermind.Facade/Proxy/Models/BlockModel.cs | 10 +++++++++- 9 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs index ddc5c402b11..da8b503dd32 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Linq; +using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Db; diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs index 1c4c5b44b22..52dc575fab0 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/AuRaBlockProcessor.cs @@ -14,6 +14,8 @@ using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Logging; using Nethermind.State; diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index 5710c850565..6899d80e8ab 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -303,12 +303,6 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, IReleaseSpec spec = _specProvider.GetSpec(header); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); - if (spec.IsEip4844Enabled) - { - header.DataGasUsed = 0; - header.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, spec); - } - return header; } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index 1577c309c6b..b195232be90 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -81,7 +81,9 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi { dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPricePerUnit( IntrinsicGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()) ?? 0); + int txAmountOfBlobs = tx.BlobVersionedHashes?.Length ?? 0; + if (dataGasPrice > tx.MaxFeePerDataGas) { if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, data gas fee is too low."); diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index e02a2269ed0..6878222fe9d 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -216,7 +216,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str int blobsInBlock = 0; UInt256? dataGasPrice = null; - for (int txIndex = block.Transactions.Length - 1; txIndex >= 0; txIndex--) + for (int txIndex = 0; txIndex < block.Transactions.Length; txIndex++) { Transaction transaction = block.Transactions[txIndex]; if (!transaction.SupportsBlobs) diff --git a/src/Nethermind/Nethermind.Core/BlockHeader.cs b/src/Nethermind/Nethermind.Core/BlockHeader.cs index 6c53d0a9a02..d9fd16d2183 100644 --- a/src/Nethermind/Nethermind.Core/BlockHeader.cs +++ b/src/Nethermind/Nethermind.Core/BlockHeader.cs @@ -67,8 +67,8 @@ public BlockHeader( public long? AuRaStep { get; set; } public UInt256 BaseFeePerGas { get; set; } public Keccak? WithdrawalsRoot { get; set; } - public ulong? ExcessDataGas { get; set; } public ulong? DataGasUsed { get; set; } + public ulong? ExcessDataGas { get; set; } public bool HasBody => (TxRoot is not null && TxRoot != Keccak.EmptyTreeHash) || (UnclesHash is not null && UnclesHash != Keccak.OfAnEmptySequenceRlp) || (WithdrawalsRoot is not null && WithdrawalsRoot != Keccak.EmptyTreeHash); diff --git a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs index 926a5bc5d6e..32ff0137504 100644 --- a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using Nethermind.Core.Extensions; using Nethermind.Int256; namespace Nethermind.Core; @@ -11,10 +10,10 @@ public class Eip4844Constants public const int MinBlobsPerTransaction = 1; public const ulong DataGasPerBlob = 1 << 17; - public const ulong TargetDataGasPerBlock = DataGasPerBlob * 3; - public const ulong MaxDataGasPerBlock = DataGasPerBlob * 6; + public const ulong TargetDataGasPerBlock = DataGasPerBlob * 2; + public const ulong MaxDataGasPerBlock = DataGasPerBlob * 4; public const ulong MaxDataGasPerTransaction = MaxDataGasPerBlock; - public static readonly UInt256 DataGasUpdateFraction = 3338477; + public static readonly UInt256 DataGasUpdateFraction = 2225652; public static readonly UInt256 MinDataGasPrice = 1; } diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index a561975011f..daa0ecffa9d 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -161,9 +161,9 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) yield return (Build.A.Transaction.TestObject, 1000, 0); yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(0).TestObject, 1000, 0); yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 0, 131072); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 10000000, 11665408); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 10000000, 2490368); yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 0, 131072000); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 10000000, 11665408000); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 10000000, 2490368000); } [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] diff --git a/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs b/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs index 9112c25105e..ed83512f93b 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; +using Newtonsoft.Json; namespace Nethermind.Facade.Proxy.Models; @@ -28,5 +29,12 @@ public class BlockModel public UInt256 TotalDifficulty { get; set; } public List Transactions { get; set; } public Keccak TransactionsRoot { get; set; } - public UInt256? ExcessDataGas { get; set; } + + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? DataGasUsed { get; set; } + + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? ExcessDataGas { get; set; } } From d41f11050afab3062e7e6f1f2ed419e93bd51b5f Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 12 Jun 2023 12:13:06 +0300 Subject: [PATCH 20/31] Add more blob space --- src/Nethermind/Nethermind.Core/Eip4844Constants.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs index 32ff0137504..0df02f30d78 100644 --- a/src/Nethermind/Nethermind.Core/Eip4844Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip4844Constants.cs @@ -10,10 +10,10 @@ public class Eip4844Constants public const int MinBlobsPerTransaction = 1; public const ulong DataGasPerBlob = 1 << 17; - public const ulong TargetDataGasPerBlock = DataGasPerBlob * 2; - public const ulong MaxDataGasPerBlock = DataGasPerBlob * 4; + public const ulong TargetDataGasPerBlock = DataGasPerBlob * 3; + public const ulong MaxDataGasPerBlock = DataGasPerBlob * 6; public const ulong MaxDataGasPerTransaction = MaxDataGasPerBlock; - public static readonly UInt256 DataGasUpdateFraction = 2225652; + public static readonly UInt256 DataGasUpdateFraction = 3338477; public static readonly UInt256 MinDataGasPrice = 1; } From d2b5311b8b0602fda36684b6f935a82e4743e795 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 12 Jun 2023 15:53:50 +0300 Subject: [PATCH 21/31] Fix tests; clean up --- .../Validators/TxValidatorTests.cs | 4 +- .../Producers/BlockProducerEnvFactory.cs | 1 - .../IntrinsicGasCalculatorTests.cs | 64 +++++++++++-------- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 19 ++---- .../TransactionProcessor.cs | 2 + .../Proxy/Models/BlockModel.cs | 64 +++++++++++-------- .../EthModuleBenchmarks.cs | 2 +- .../AssertionsSetup.cs | 22 +++++++ .../AssertionsSetup.cs | 22 +++++++ 9 files changed, 128 insertions(+), 72 deletions(-) create mode 100644 src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs create mode 100644 src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 58f94f1f992..4ca9670dcfe 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -292,7 +292,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) @@ -303,7 +303,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)] diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index 65820969f0e..3d88b53ba6a 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Blockchain; -using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Config; using Nethermind.Consensus.Comparers; diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index daa0ecffa9d..8ac8317c463 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -116,28 +116,16 @@ void Test(IReleaseSpec spec, bool isAfterRepricing) Test(Cancun.Instance, true); } - public static IEnumerable<(ulong parentExcessDataGas, int newBlobsCount, ulong expectedCost)> ExcessDataGasTestCaseSource() - { - yield return (0, 0, 0); - yield return (0, 1, 0); - yield return (0, 2, 0); - yield return (0, 3, Eip4844Constants.DataGasPerBlob * (3 - 2)); - yield return (100000, 3, Eip4844Constants.DataGasPerBlob + 100000); - yield return (Eip4844Constants.TargetDataGasPerBlock, 1, Eip4844Constants.DataGasPerBlob * 1); - yield return (Eip4844Constants.TargetDataGasPerBlock, 0, 0); - yield return (Eip4844Constants.TargetDataGasPerBlock, 2, Eip4844Constants.DataGasPerBlob * 2); - } - [TestCaseSource(nameof(ExcessDataGasTestCaseSource))] - public void Blobs_excess_data_gas_is_calculated_correctly((ulong excessDataGas, int newBlobsCount, ulong expectedCost) testCase) + public void Excess_data_gas_is_calculated_correctly((ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas) testCase) { void Test(IReleaseSpec spec, bool areBlobsEnabled) { - BlockHeader header = Build.A.BlockHeader - .WithDataGasUsed(IntrinsicGasCalculator.CalculateDataGas(testCase.newBlobsCount)) - .WithExcessDataGas(testCase.excessDataGas).TestObject; - IntrinsicGasCalculator.CalculateExcessDataGas(header, spec).Should() - .Be(areBlobsEnabled ? testCase.expectedCost : null); + BlockHeader parentHeader = Build.A.BlockHeader + .WithDataGasUsed(IntrinsicGasCalculator.CalculateDataGas(testCase.parentBlobsCount)) + .WithExcessDataGas(testCase.parentExcessDataGas).TestObject; + IntrinsicGasCalculator.CalculateExcessDataGas(parentHeader, spec).Should() + .Be(areBlobsEnabled ? testCase.expectedExcessDataGas : null); } Test(Homestead.Instance, false); @@ -155,6 +143,37 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) Test(Cancun.Instance, true); } + [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] + public void Blobs_intrinsic_cost_is_calculated_properly( + (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) + { + BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; + IntrinsicGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() + .Be(testCase.expectedCost); + } + + public static IEnumerable<(ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas)> ExcessDataGasTestCaseSource() + { + yield return (0, 0, 0); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) - 1, 0); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 0); + yield return (100000, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 100000); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) + 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 0, 0); + yield return (Eip4844Constants.TargetDataGasPerBlock, 2, Eip4844Constants.DataGasPerBlob * 2); + yield return (Eip4844Constants.MaxDataGasPerBlock, 1, Eip4844Constants.TargetDataGasPerBlock + Eip4844Constants.DataGasPerBlob * 1); + yield return ( + Eip4844Constants.MaxDataGasPerBlock, + (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), + Eip4844Constants.MaxDataGasPerBlock); + yield return ( + Eip4844Constants.MaxDataGasPerBlock, + (int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob), + Eip4844Constants.MaxDataGasPerBlock * 2 - Eip4844Constants.TargetDataGasPerBlock + ); + } + public static IEnumerable<(Transaction tx, ulong excessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() { yield return (Build.A.Transaction.TestObject, 0, 0); @@ -165,14 +184,5 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 0, 131072000); yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 10000000, 2490368000); } - - [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] - public void Blobs_intrinsic_cost_is_calculated_properly( - (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) - { - BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; - IntrinsicGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() - .Be(testCase.expectedCost); - } } } diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index 2f8d1afe11f..caa7706b330 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -94,7 +94,8 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release return accessListCost; } - public static ulong CalculateDataGas(int blobCount) => (ulong)blobCount * Eip4844Constants.DataGasPerBlob; + public static ulong CalculateDataGas(int blobCount) => + (ulong)blobCount * Eip4844Constants.DataGasPerBlob; public static ulong CalculateDataGas(Transaction transaction) => CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); @@ -102,18 +103,10 @@ public static ulong CalculateDataGas(Transaction transaction) => public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => CalculateDataGas(transaction) * CalculateDataGasPricePerUnit(header); - public static UInt256 CalculateDataGasPrice(BlockHeader header) => - header.DataGasUsed!.Value * CalculateDataGasPricePerUnit(header); - - public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) - { - if (header.ExcessDataGas is null) - { - throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)); - } - - return CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); - } + public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) => + header.ExcessDataGas is null + ? throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)) + : CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) { diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index e30b9fc3887..877702436ad 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -406,6 +406,8 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra _worldState.Restore(snapshot); } + if (_logger.IsTrace) _logger.Trace("Gas spent: " + spentGas); + Address gasBeneficiary = block.GasBeneficiary; bool gasBeneficiaryNotDestroyed = substate?.DestroyList.Contains(gasBeneficiary) != true; if (statusCode == StatusCode.Failure || gasBeneficiaryNotDestroyed) diff --git a/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs b/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs index ed83512f93b..656e5c9f6ed 100644 --- a/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs +++ b/src/Nethermind/Nethermind.Facade/Proxy/Models/BlockModel.cs @@ -5,36 +5,44 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Int256; -using Newtonsoft.Json; -namespace Nethermind.Facade.Proxy.Models; - -public class BlockModel +namespace Nethermind.Facade.Proxy.Models { - public UInt256 Difficulty { get; set; } - public byte[] ExtraData { get; set; } - public UInt256 GasLimit { get; set; } - public UInt256 GasUsed { get; set; } - public Keccak Hash { get; set; } - public Address Miner { get; set; } - public Keccak MixHash { get; set; } - public UInt256 Nonce { get; set; } - public UInt256 Number { get; set; } - public Keccak ParentHash { get; set; } - public Keccak ReceiptsRoot { get; set; } - public Keccak Sha3Uncles { get; set; } - public UInt256 Size { get; set; } - public Keccak StateRoot { get; set; } - public ulong Timestamp { get; set; } - public UInt256 TotalDifficulty { get; set; } - public List Transactions { get; set; } - public Keccak TransactionsRoot { get; set; } - - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public ulong? DataGasUsed { get; set; } + public class BlockModel + { + public UInt256 Difficulty { get; set; } + public byte[] ExtraData { get; set; } + public UInt256 GasLimit { get; set; } + public UInt256 GasUsed { get; set; } + public Keccak Hash { get; set; } + public Address Miner { get; set; } + public Keccak MixHash { get; set; } + public UInt256 Nonce { get; set; } + public UInt256 Number { get; set; } + public Keccak ParentHash { get; set; } + public Keccak ReceiptsRoot { get; set; } + public Keccak Sha3Uncles { get; set; } + public UInt256 Size { get; set; } + public Keccak StateRoot { get; set; } + public ulong Timestamp { get; set; } + public UInt256 TotalDifficulty { get; set; } + public List Transactions { get; set; } + public Keccak TransactionsRoot { get; set; } + public Block ToBlock() + { + Block block = new(new BlockHeader(ParentHash, Sha3Uncles, Miner, Difficulty, (long)Number, + (long)GasLimit, Timestamp, ExtraData)); - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public ulong? ExcessDataGas { get; set; } + block.Header.StateRoot = StateRoot; + block.Header.GasUsed = (long)GasUsed; + block.Header.Hash = Hash; + block.Header.MixHash = MixHash; + block.Header.Nonce = (ulong)Nonce; + block.Header.ReceiptsRoot = ReceiptsRoot; + block.Header.TotalDifficulty = TotalDifficulty; + block.Header.TxRoot = TransactionsRoot; + return block; + } + } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 4bf607ae266..922541c2d0c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -80,7 +80,7 @@ TransactionProcessor transactionProcessor IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor = new BlockProcessor.BlockValidationTransactionsExecutor(transactionProcessor, stateProvider); BlockProcessor blockProcessor = new(specProvider, Always.Valid, new RewardCalculator(specProvider), transactionsExecutor, - stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, blockTree, LimboLogs.Instance); + stateProvider, NullReceiptStorage.Instance, NullWitnessCollector.Instance, LimboLogs.Instance); EthereumEcdsa ecdsa = new(specProvider.ChainId, LimboLogs.Instance); BlockchainProcessor blockchainProcessor = new( diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs new file mode 100644 index 00000000000..4ea6730bd46 --- /dev/null +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AssertionsSetup.cs @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using NUnit.Framework; +using NUnit.Framework.Internal; +using FluentAssertions; +using Nethermind.Core; + +namespace Nethermind; + +/// +/// Global settings for the fluent assertions, works for the current assembly only. +/// +[SetUpFixture] +public class AssertionsSetup +{ + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + AssertionOptions.AssertEquivalencyUsing(options => options.Excluding(c => c.Name == nameof(BlockHeader.MaybeParent))); + } +} diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs new file mode 100644 index 00000000000..4ea6730bd46 --- /dev/null +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/AssertionsSetup.cs @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using NUnit.Framework; +using NUnit.Framework.Internal; +using FluentAssertions; +using Nethermind.Core; + +namespace Nethermind; + +/// +/// Global settings for the fluent assertions, works for the current assembly only. +/// +[SetUpFixture] +public class AssertionsSetup +{ + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + AssertionOptions.AssertEquivalencyUsing(options => options.Excluding(c => c.Name == nameof(BlockHeader.MaybeParent))); + } +} From 991340417d80b6ce3f35b0a61d4f01a85cb1f92d Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Wed, 14 Jun 2023 12:48:30 +0300 Subject: [PATCH 22/31] Add tests, refacator --- .../Processing/BlockProcessor.cs | 2 +- .../Producers/TxPoolTxSource.cs | 6 +- .../Validators/BlockValidator.cs | 4 +- .../Validators/HeaderValidator.cs | 2 +- .../Validators/TxValidator.cs | 2 +- .../DataGasCalculatorTests.cs | 86 ++++++++++ .../IntrinsicGasCalculatorTests.cs | 69 -------- .../TransactionProcessorEip4844Tests.cs | 156 ++++++++++++++++++ .../TransactionProcessorTests.cs | 1 - .../Nethermind.Evm/DataGasCalculator.cs | 77 +++++++++ .../Nethermind.Evm/IntrinsicGasCalculator.cs | 56 ------- .../Nethermind.Evm/TransactionExtensions.cs | 4 +- .../TransactionProcessor.cs | 2 +- .../Nethermind.Facade/BlockchainBridge.cs | 4 +- .../EngineModuleTests.V3.cs | 2 +- .../BlockProduction/PostMergeBlockProducer.cs | 2 +- 16 files changed, 334 insertions(+), 141 deletions(-) create mode 100644 src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs create mode 100644 src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs create mode 100644 src/Nethermind/Nethermind.Evm/DataGasCalculator.cs diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index 625264573c2..d1eb8b3ae03 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -229,7 +229,7 @@ protected virtual TxReceipt[] ProcessBlock( if (spec.IsEip4844Enabled) { - block.Header.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas( + block.Header.DataGasUsed = DataGasCalculator.CalculateDataGas( block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index b195232be90..d26c9390ad4 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -79,8 +79,8 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi if (tx.SupportsBlobs) { - dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPricePerUnit( - IntrinsicGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()) ?? 0); + dataGasPrice ??= DataGasCalculator.CalculateDataGasPricePerUnit( + DataGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()) ?? 0); int txAmountOfBlobs = tx.BlobVersionedHashes?.Length ?? 0; @@ -90,7 +90,7 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi continue; } - if (IntrinsicGasCalculator.CalculateDataGas(blobsCounter + txAmountOfBlobs) > + if (DataGasCalculator.CalculateDataGas(blobsCounter + txAmountOfBlobs) > Eip4844Constants.MaxDataGasPerBlock) { if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, no more blob space."); diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 6878222fe9d..55ea2a3cd88 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -224,7 +224,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str continue; } - if (transaction.MaxFeePerDataGas < (dataGasPrice ??= IntrinsicGasCalculator.CalculateDataGasPricePerUnit(block.Header))) + if (transaction.MaxFeePerDataGas < (dataGasPrice ??= DataGasCalculator.CalculateDataGasPricePerUnit(block.Header))) { error = $"A transaction has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; if (_logger.IsWarn) _logger.Warn(error); @@ -234,7 +234,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str blobsInBlock += transaction.BlobVersionedHashes!.Length; } - ulong dataGasUsed = IntrinsicGasCalculator.CalculateDataGas(blobsInBlock); + ulong dataGasUsed = DataGasCalculator.CalculateDataGas(blobsInBlock); if (dataGasUsed > Eip4844Constants.MaxDataGasPerBlock) { error = $"A block cannot have more than {Eip4844Constants.MaxDataGasPerBlock} data gas."; diff --git a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs index 060454d357e..66d77ad4694 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/HeaderValidator.cs @@ -310,7 +310,7 @@ private bool ValidateDataGasFields(BlockHeader header, BlockHeader parentHeader, return false; } - UInt256? expectedExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parentHeader, spec); + UInt256? expectedExcessDataGas = DataGasCalculator.CalculateExcessDataGas(parentHeader, spec); if (header.ExcessDataGas != expectedExcessDataGas) { diff --git a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs index 923586c9dac..21fd0dcc1c0 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/TxValidator.cs @@ -119,7 +119,7 @@ transaction.BlobVersionedHashes is null && if (transaction.To is null || transaction.MaxFeePerDataGas is null || transaction.BlobVersionedHashes is null || - IntrinsicGasCalculator.CalculateDataGas(transaction.BlobVersionedHashes!.Length) > Eip4844Constants.MaxDataGasPerTransaction || + DataGasCalculator.CalculateDataGas(transaction.BlobVersionedHashes!.Length) > Eip4844Constants.MaxDataGasPerTransaction || transaction.BlobVersionedHashes!.Length < Eip4844Constants.MinBlobsPerTransaction) { return false; diff --git a/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs new file mode 100644 index 00000000000..901fd7abae2 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Core.Test.Builders; +using Nethermind.Int256; +using Nethermind.Specs.Forks; +using NUnit.Framework; + +namespace Nethermind.Evm.Test; + +[TestFixture] +public class DataGasCalculatorTests +{ + [TestCaseSource(nameof(ExcessDataGasTestCaseSource))] + public void Excess_data_gas_is_calculated_properly((ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas) testCase) + { + void Test(IReleaseSpec spec, bool areBlobsEnabled) + { + BlockHeader parentHeader = Build.A.BlockHeader + .WithDataGasUsed(DataGasCalculator.CalculateDataGas(testCase.parentBlobsCount)) + .WithExcessDataGas(testCase.parentExcessDataGas).TestObject; + DataGasCalculator.CalculateExcessDataGas(parentHeader, spec).Should() + .Be(areBlobsEnabled ? testCase.expectedExcessDataGas : null); + } + + Test(Homestead.Instance, false); + Test(Frontier.Instance, false); + Test(SpuriousDragon.Instance, false); + Test(TangerineWhistle.Instance, false); + Test(Byzantium.Instance, false); + Test(Constantinople.Instance, false); + Test(ConstantinopleFix.Instance, false); + Test(Istanbul.Instance, false); + Test(MuirGlacier.Instance, false); + Test(Berlin.Instance, false); + Test(GrayGlacier.Instance, false); + Test(Shanghai.Instance, false); + Test(Cancun.Instance, true); + } + + [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] + public void Data_gas_cost_is_calculated_properly( + (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) + { + BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; + DataGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() + .Be(testCase.expectedCost); + } + + public static IEnumerable<(ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas)> ExcessDataGasTestCaseSource() + { + yield return (0, 0, 0); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) - 1, 0); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 0); + yield return (100000, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 100000); + yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) + 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 1, Eip4844Constants.DataGasPerBlob * 1); + yield return (Eip4844Constants.TargetDataGasPerBlock, 0, 0); + yield return (Eip4844Constants.TargetDataGasPerBlock, 2, Eip4844Constants.DataGasPerBlob * 2); + yield return (Eip4844Constants.MaxDataGasPerBlock, 1, Eip4844Constants.TargetDataGasPerBlock + Eip4844Constants.DataGasPerBlob * 1); + yield return ( + Eip4844Constants.MaxDataGasPerBlock, + (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), + Eip4844Constants.MaxDataGasPerBlock); + yield return ( + Eip4844Constants.MaxDataGasPerBlock, + (int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob), + Eip4844Constants.MaxDataGasPerBlock * 2 - Eip4844Constants.TargetDataGasPerBlock + ); + } + + public static IEnumerable<(Transaction tx, ulong excessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() + { + yield return (Build.A.Transaction.TestObject, 0, 0); + yield return (Build.A.Transaction.TestObject, 1000, 0); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(0).TestObject, 1000, 0); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 0, 131072); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 10000000, 2490368); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 0, 131072000); + yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 10000000, 2490368000); + } +} diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index 8ac8317c463..f830b2483cc 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -115,74 +115,5 @@ void Test(IReleaseSpec spec, bool isAfterRepricing) Test(Shanghai.Instance, true); Test(Cancun.Instance, true); } - - [TestCaseSource(nameof(ExcessDataGasTestCaseSource))] - public void Excess_data_gas_is_calculated_correctly((ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas) testCase) - { - void Test(IReleaseSpec spec, bool areBlobsEnabled) - { - BlockHeader parentHeader = Build.A.BlockHeader - .WithDataGasUsed(IntrinsicGasCalculator.CalculateDataGas(testCase.parentBlobsCount)) - .WithExcessDataGas(testCase.parentExcessDataGas).TestObject; - IntrinsicGasCalculator.CalculateExcessDataGas(parentHeader, spec).Should() - .Be(areBlobsEnabled ? testCase.expectedExcessDataGas : null); - } - - Test(Homestead.Instance, false); - Test(Frontier.Instance, false); - Test(SpuriousDragon.Instance, false); - Test(TangerineWhistle.Instance, false); - Test(Byzantium.Instance, false); - Test(Constantinople.Instance, false); - Test(ConstantinopleFix.Instance, false); - Test(Istanbul.Instance, false); - Test(MuirGlacier.Instance, false); - Test(Berlin.Instance, false); - Test(GrayGlacier.Instance, false); - Test(Shanghai.Instance, false); - Test(Cancun.Instance, true); - } - - [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] - public void Blobs_intrinsic_cost_is_calculated_properly( - (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) - { - BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; - IntrinsicGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() - .Be(testCase.expectedCost); - } - - public static IEnumerable<(ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas)> ExcessDataGasTestCaseSource() - { - yield return (0, 0, 0); - yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) - 1, 0); - yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 0); - yield return (100000, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), 100000); - yield return (0, (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob) + 1, Eip4844Constants.DataGasPerBlob * 1); - yield return (Eip4844Constants.TargetDataGasPerBlock, 1, Eip4844Constants.DataGasPerBlob * 1); - yield return (Eip4844Constants.TargetDataGasPerBlock, 0, 0); - yield return (Eip4844Constants.TargetDataGasPerBlock, 2, Eip4844Constants.DataGasPerBlob * 2); - yield return (Eip4844Constants.MaxDataGasPerBlock, 1, Eip4844Constants.TargetDataGasPerBlock + Eip4844Constants.DataGasPerBlob * 1); - yield return ( - Eip4844Constants.MaxDataGasPerBlock, - (int)(Eip4844Constants.TargetDataGasPerBlock / Eip4844Constants.DataGasPerBlob), - Eip4844Constants.MaxDataGasPerBlock); - yield return ( - Eip4844Constants.MaxDataGasPerBlock, - (int)(Eip4844Constants.MaxDataGasPerBlock / Eip4844Constants.DataGasPerBlob), - Eip4844Constants.MaxDataGasPerBlock * 2 - Eip4844Constants.TargetDataGasPerBlock - ); - } - - public static IEnumerable<(Transaction tx, ulong excessDataGas, UInt256 expectedCost)> BlobDataGasCostTestCaseSource() - { - yield return (Build.A.Transaction.TestObject, 0, 0); - yield return (Build.A.Transaction.TestObject, 1000, 0); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(0).TestObject, 1000, 0); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 0, 131072); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1).TestObject, 10000000, 2490368); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 0, 131072000); - yield return (Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject, 10000000, 2490368000); - } } } diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs new file mode 100644 index 00000000000..6408fa4afe2 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Core; +using Nethermind.Core.Extensions; +using Nethermind.Core.Specs; +using Nethermind.Specs; +using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; +using Nethermind.Db; +using Nethermind.Int256; +using Nethermind.Evm.Tracing; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.Logging; +using Nethermind.Specs.Forks; +using Nethermind.State; +using Nethermind.Trie.Pruning; +using NUnit.Framework; +using System.Collections.Generic; + +namespace Nethermind.Evm.Test; + +[TestFixture] +internal class TransactionProcessorEip4844Tests +{ + private ISpecProvider _specProvider; + private IEthereumEcdsa _ethereumEcdsa; + private TransactionProcessor _transactionProcessor; + private IWorldState _stateProvider; + + [SetUp] + public void Setup() + { + MemDb stateDb = new(); + _specProvider = new TestSpecProvider(Cancun.Instance); + TrieStore trieStore = new(stateDb, LimboLogs.Instance); + _stateProvider = new WorldState(trieStore, new MemDb(), LimboLogs.Instance); + VirtualMachine virtualMachine = new(TestBlockhashProvider.Instance, _specProvider, LimboLogs.Instance); + _transactionProcessor = new TransactionProcessor(_specProvider, _stateProvider, virtualMachine, LimboLogs.Instance); + _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance); + } + + + [TestCaseSource(nameof(BalanceIsAffectedByDataGasTestCaseSource))] + [TestCaseSource(nameof(BalanceIsNotAffectedWhenNotEnoughFunds))] + public UInt256 Balance_is_affected_by_data_gas(UInt256 balance, int blobCount, ulong maxFeePerDataGas, ulong excessDataGas) + { + _stateProvider.CreateAccount(TestItem.AddressA, balance); + _stateProvider.Commit(_specProvider.GenesisSpec); + _stateProvider.CommitTree(0); + + long gasLimit = GasCostOf.Transaction; + Transaction blobTx = Build.A.Transaction + .WithValue(0) + .WithGasPrice(1) + .WithMaxFeePerGas(1) + .WithMaxFeePerDataGas(maxFeePerDataGas) + .WithGasLimit(gasLimit) + .WithShardBlobTxTypeAndFields(blobCount) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA) + .TestObject; + + Block block = Build.A.Block + .WithNumber(1) + .WithTransactions(blobTx) + .WithGasLimit(gasLimit) + .WithExcessDataGas(excessDataGas) + .WithBaseFeePerGas(1) + .TestObject; + + _transactionProcessor.Execute(blobTx, block.Header, NullTxTracer.Instance); + UInt256 deltaBalance = balance - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); + + return deltaBalance; + } + + public static IEnumerable BalanceIsAffectedByDataGasTestCaseSource() + { + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), 1, 1ul, 0ul) + { + TestName = "Data gas consumed for 1 blob, minimal balance", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), + }; + yield return new TestCaseData(1.Ether(), 1, 1ul, 0ul) + { + TestName = "Data gas consumed for 1 blob", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), + }; + yield return new TestCaseData(1.Ether(), 2, 1ul, 0ul) + { + TestName = "Data gas consumed for 2 blobs", + ExpectedResult = (UInt256)(GasCostOf.Transaction + 2 * Eip4844Constants.DataGasPerBlob), + }; + yield return new TestCaseData(1.Ether(), (int)(Eip4844Constants.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob), 1ul, 0ul) + { + TestName = "Data gas consumed for max blobs", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.MaxDataGasPerTransaction), + }; + yield return new TestCaseData(1.Ether(), 1, 10ul, 0ul) + { + TestName = $"Data gas consumed for 1 blob, with {nameof(Transaction.MaxFeePerDataGas)} more than needed", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), + }; + yield return new TestCaseData(1.Ether(), 1, 10ul, (ulong)Eip4844Constants.DataGasUpdateFraction) + { + TestName = $"Data gas consumed for 1 blob, with data gas price hiking", + ExpectedResult = (UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob * 2), + }; + } + + public static IEnumerable BalanceIsNotAffectedWhenNotEnoughFunds() + { + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob - 1), 1, 1ul, 0ul) + { + TestName = $"Rejected if balance is not enough, all funds are returned", + ExpectedResult = UInt256.Zero, + }; + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), 1, 10ul, (ulong)Eip4844Constants.DataGasUpdateFraction) + { + TestName = $"Rejected if balance is not enough due to data gas price hiking, all funds are returned", + ExpectedResult = UInt256.Zero, + }; + } + + [Test] + public void Balance_is_not_changed_on_call_and_restore() + { + UInt256 initialBalance = 1.Ether(); + _stateProvider.CreateAccount(TestItem.AddressA, initialBalance); + _stateProvider.Commit(_specProvider.GenesisSpec); + _stateProvider.CommitTree(0); + + long gasLimit = GasCostOf.Transaction; + Transaction blobTx = Build.A.Transaction + .WithValue(0) + .WithGasPrice(1) + .WithMaxFeePerGas(1) + .WithMaxFeePerDataGas(1) + .WithGasLimit(gasLimit) + .WithShardBlobTxTypeAndFields(1) + .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA) + .TestObject; + + Block block = Build.A.Block + .WithNumber(1) + .WithTransactions(blobTx) + .WithGasLimit(gasLimit) + .WithExcessDataGas(0) + .WithBaseFeePerGas(1) + .TestObject; + + _transactionProcessor.CallAndRestore(blobTx, block.Header, NullTxTracer.Instance); + UInt256 newBalance = _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); + Assert.That(newBalance, Is.EqualTo(initialBalance)); + } +} diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs index 21fffcb574e..bfb4470881d 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs @@ -24,7 +24,6 @@ using Nethermind.Trie.Pruning; using NUnit.Framework; using Nethermind.Config; -using Nethermind.Core.Test; namespace Nethermind.Evm.Test { diff --git a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs new file mode 100644 index 00000000000..346d3743ea7 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Int256; + +namespace Nethermind.Evm; + +public static class DataGasCalculator +{ + public static ulong CalculateDataGas(int blobCount) => + (ulong)blobCount * Eip4844Constants.DataGasPerBlob; + + public static ulong CalculateDataGas(Transaction transaction) => + CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); + + public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => + CalculateDataGas(transaction) * CalculateDataGasPricePerUnit(header); + + public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) => + header.ExcessDataGas is null + ? throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)) + : CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); + + public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) + { + static UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) + { + UInt256 output = UInt256.Zero; + + UInt256 numAccum = factor * denominator; + + for (UInt256 i = 1; numAccum > 0; i++) + { + output += numAccum; + numAccum *= num; + numAccum /= i * denominator; + } + + return output / denominator; + } + + UInt256 scaleDueToParentExcessDataGas = + FakeExponential(Eip4844Constants.MinDataGasPrice, excessDataGas, Eip4844Constants.DataGasUpdateFraction); + return scaleDueToParentExcessDataGas; + } + + public static ulong? CalculateExcessDataGas(BlockHeader? parentBlockHeader, IReleaseSpec releaseSpec) + { + if (!releaseSpec.IsEip4844Enabled) + { + return null; + } + + if (parentBlockHeader is null) + { + return 0; + } + + ulong excessDataGas = parentBlockHeader.ExcessDataGas ?? 0; + excessDataGas += parentBlockHeader.DataGasUsed ?? 0; + return excessDataGas < Eip4844Constants.TargetDataGasPerBlock + ? 0 + : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); + } + + public static ulong? CalculateExcessDataGas(ulong? parentExcessDataGas, ulong? parentDataGasUsed) + { + ulong excessDataGas = parentExcessDataGas ?? 0; + excessDataGas += parentDataGasUsed ?? 0; + return excessDataGas < Eip4844Constants.TargetDataGasPerBlock + ? 0 + : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); + } +} diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index caa7706b330..b030b204bb2 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -93,60 +93,4 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release return accessListCost; } - - public static ulong CalculateDataGas(int blobCount) => - (ulong)blobCount * Eip4844Constants.DataGasPerBlob; - - public static ulong CalculateDataGas(Transaction transaction) => - CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); - - public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => - CalculateDataGas(transaction) * CalculateDataGasPricePerUnit(header); - - public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) => - header.ExcessDataGas is null - ? throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)) - : CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); - - public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) - { - static UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) - { - UInt256 output = UInt256.Zero; - - UInt256 numAccum = factor * denominator; - - for (UInt256 i = 1; numAccum > 0; i++) - { - output += numAccum; - numAccum *= num; - numAccum /= i * denominator; - } - - return output / denominator; - } - - UInt256 scaleDueToParentExcessDataGas = - FakeExponential(Eip4844Constants.MinDataGasPrice, excessDataGas, Eip4844Constants.DataGasUpdateFraction); - return scaleDueToParentExcessDataGas; - } - - public static ulong? CalculateExcessDataGas(BlockHeader? parentBlockHeader, IReleaseSpec releaseSpec) - { - if (!releaseSpec.IsEip4844Enabled) - { - return null; - } - - if (parentBlockHeader is null) - { - return 0; - } - - ulong excessDataGas = parentBlockHeader.ExcessDataGas ?? 0; - excessDataGas += parentBlockHeader.DataGasUsed ?? 0; - return excessDataGas < Eip4844Constants.TargetDataGasPerBlock - ? 0 - : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); - } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs index e0bd18c1860..a905242f6ca 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs @@ -22,8 +22,8 @@ public static TxGasInfo GetGasInfo(this Transaction tx, bool is1559Enabled, Bloc UInt256? dataGasPrice = null; if (tx.SupportsBlobs) { - dataGas = IntrinsicGasCalculator.CalculateDataGas(tx); - dataGasPrice = IntrinsicGasCalculator.CalculateDataGasPrice(header, tx); + dataGas = DataGasCalculator.CalculateDataGas(tx); + dataGasPrice = DataGasCalculator.CalculateDataGasPrice(header, tx); } return new(effectiveGasPrice, dataGasPrice, dataGas); diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 877702436ad..5613331b6dc 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -241,7 +241,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } UInt256 dataGasPrice = spec.IsEip4844Enabled - ? IntrinsicGasCalculator.CalculateDataGasPrice(block, transaction) + ? DataGasCalculator.CalculateDataGasPrice(block, transaction) : UInt256.Zero; UInt256 senderReservedGasPayment = (ulong)gasLimit * effectiveGasPrice + dataGasPrice; diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index dbc10993fb9..28d3780250a 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -270,9 +270,9 @@ private void CallAndRestore( if (releaseSpec.IsEip4844Enabled) { - callHeader.DataGasUsed = IntrinsicGasCalculator.CalculateDataGas(transaction); + callHeader.DataGasUsed = DataGasCalculator.CalculateDataGas(transaction); callHeader.ExcessDataGas = treatBlockHeaderAsParentBlock - ? IntrinsicGasCalculator.CalculateExcessDataGas(blockHeader, releaseSpec) + ? DataGasCalculator.CalculateExcessDataGas(blockHeader, releaseSpec) : blockHeader.ExcessDataGas; } callHeader.MixHash = blockHeader.MixHash; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index 31085f61eb2..a9525f36cbf 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -62,7 +62,7 @@ public async Task PayloadV3_should_return_all_the_blobs(int blobTxCount) (IEngineRpcModule rpcModule, string payloadId) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); var result = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); BlobsBundleV1 getPayloadResultBlobsBundle = result.Data!.BlobsBundle!; - Assert.That(result.Data.ExecutionPayload.DataGasUsed, Is.EqualTo(IntrinsicGasCalculator.CalculateDataGas(blobTxCount))); + Assert.That(result.Data.ExecutionPayload.DataGasUsed, Is.EqualTo(DataGasCalculator.CalculateDataGas(blobTxCount))); Assert.That(result.Data.ExecutionPayload.ExcessDataGas, Is.Not.Null); Assert.That(getPayloadResultBlobsBundle.Blobs!.Length, Is.EqualTo(blobTxCount)); Assert.That(getPayloadResultBlobsBundle.Commitments!.Length, Is.EqualTo(blobTxCount)); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs index 37a35a2f65d..df8bc662810 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs @@ -101,7 +101,7 @@ private void AmendHeader(BlockHeader blockHeader, BlockHeader parent) if (spec.IsEip4844Enabled) { blockHeader.DataGasUsed = 0; - blockHeader.ExcessDataGas = IntrinsicGasCalculator.CalculateExcessDataGas(parent, spec); + blockHeader.ExcessDataGas = DataGasCalculator.CalculateExcessDataGas(parent, spec); } } } From 6105dfbc868f5854b6f5e279f5f106b283203282 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Wed, 14 Jun 2023 22:02:05 +0300 Subject: [PATCH 23/31] Fix MaxFeePerDataGas affects consensus on low balance --- .../Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs | 5 +++++ .../TransactionProcessing/TransactionProcessor.cs | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs index 6408fa4afe2..b72280be58f 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs @@ -120,6 +120,11 @@ public static IEnumerable BalanceIsNotAffectedWhenNotEnoughFunds() TestName = $"Rejected if balance is not enough due to data gas price hiking, all funds are returned", ExpectedResult = UInt256.Zero, }; + yield return new TestCaseData((UInt256)(GasCostOf.Transaction + Eip4844Constants.DataGasPerBlob), 1, 2ul, 0ul) + { + TestName = $"Rejected if balance does not cover {nameof(Transaction.MaxFeePerDataGas)}, all funds are returned", + ExpectedResult = UInt256.Zero, + }; } [Test] diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 23276507354..926404c8d08 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -258,8 +258,12 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra return; } + UInt256 maxDataGasPrice = spec.IsEip4844Enabled + ? DataGasCalculator.CalculateDataGas(transaction) * transaction.MaxFeePerDataGas.Value + : UInt256.Zero; + if (!noValidation && spec.IsEip1559Enabled && !transaction.IsFree() && - (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + dataGasPrice > senderBalance) + (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + maxDataGasPrice > senderBalance) { TraceLogInvalidTx(transaction, $"INSUFFICIENT_MAX_FEE_PER_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}"); From da4d479b1cb92d494d11a7a56b9a521fc1f66081 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 15 Jun 2023 10:55:59 +0300 Subject: [PATCH 24/31] Improve max fee per data gas fix --- .../TransactionProcessorEip4844Tests.cs | 40 +++---------------- .../TransactionProcessor.cs | 36 +++++++++++------ 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs index b72280be58f..d3122d9ab61 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorEip4844Tests.cs @@ -43,7 +43,7 @@ public void Setup() [TestCaseSource(nameof(BalanceIsAffectedByDataGasTestCaseSource))] [TestCaseSource(nameof(BalanceIsNotAffectedWhenNotEnoughFunds))] - public UInt256 Balance_is_affected_by_data_gas(UInt256 balance, int blobCount, ulong maxFeePerDataGas, ulong excessDataGas) + public UInt256 Balance_is_affected_by_data_gas_on_execution(UInt256 balance, int blobCount, ulong maxFeePerDataGas, ulong excessDataGas) { _stateProvider.CreateAccount(TestItem.AddressA, balance); _stateProvider.Commit(_specProvider.GenesisSpec); @@ -68,8 +68,12 @@ public UInt256 Balance_is_affected_by_data_gas(UInt256 balance, int blobCount, u .WithBaseFeePerGas(1) .TestObject; - _transactionProcessor.Execute(blobTx, block.Header, NullTxTracer.Instance); + _transactionProcessor.CallAndRestore(blobTx, block.Header, NullTxTracer.Instance); UInt256 deltaBalance = balance - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); + Assert.That(deltaBalance, Is.EqualTo(UInt256.Zero)); + + _transactionProcessor.Execute(blobTx, block.Header, NullTxTracer.Instance); + deltaBalance = balance - _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); return deltaBalance; } @@ -126,36 +130,4 @@ public static IEnumerable BalanceIsNotAffectedWhenNotEnoughFunds() ExpectedResult = UInt256.Zero, }; } - - [Test] - public void Balance_is_not_changed_on_call_and_restore() - { - UInt256 initialBalance = 1.Ether(); - _stateProvider.CreateAccount(TestItem.AddressA, initialBalance); - _stateProvider.Commit(_specProvider.GenesisSpec); - _stateProvider.CommitTree(0); - - long gasLimit = GasCostOf.Transaction; - Transaction blobTx = Build.A.Transaction - .WithValue(0) - .WithGasPrice(1) - .WithMaxFeePerGas(1) - .WithMaxFeePerDataGas(1) - .WithGasLimit(gasLimit) - .WithShardBlobTxTypeAndFields(1) - .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA) - .TestObject; - - Block block = Build.A.Block - .WithNumber(1) - .WithTransactions(blobTx) - .WithGasLimit(gasLimit) - .WithExcessDataGas(0) - .WithBaseFeePerGas(1) - .TestObject; - - _transactionProcessor.CallAndRestore(blobTx, block.Header, NullTxTracer.Instance); - UInt256 newBalance = _stateProvider.GetBalance(TestItem.PrivateKeyA.Address); - Assert.That(newBalance, Is.EqualTo(initialBalance)); - } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 926404c8d08..5e49fecb240 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -240,7 +240,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra } } - UInt256 dataGasPrice = spec.IsEip4844Enabled + UInt256 dataGasPrice = transaction.SupportsBlobs ? DataGasCalculator.CalculateDataGasPrice(block, transaction) : UInt256.Zero; @@ -258,18 +258,30 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra return; } - UInt256 maxDataGasPrice = spec.IsEip4844Enabled - ? DataGasCalculator.CalculateDataGas(transaction) * transaction.MaxFeePerDataGas.Value - : UInt256.Zero; - - if (!noValidation && spec.IsEip1559Enabled && !transaction.IsFree() && - (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value + maxDataGasPrice > senderBalance) + if (!noValidation && spec.IsEip1559Enabled && !transaction.IsFree()) { - 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"); - return; + UInt256 maxRegularFee = (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + value; + if (maxRegularFee > senderBalance) + { + 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"); + return; + } + if (transaction.SupportsBlobs) + { + UInt256 maxDataGasPrice = DataGasCalculator.CalculateDataGas(transaction) * transaction.MaxFeePerDataGas.Value; + + if (maxRegularFee + maxDataGasPrice > senderBalance) + { + TraceLogInvalidTx(transaction, + $"INSUFFICIENT_MAX_FEE_PER_DATA_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}, MAX_FEE_PER_DATA_GAS: {transaction.MaxFeePerDataGas}"); + QuickFail(transaction, block, txTracer, eip658NotEnabled, + "insufficient MaxFeePerGas for sender balance"); + return; + } + } } if (transaction.Nonce != _worldState.GetNonce(caller)) From a6816133f5418b13bd9ffcfe9af5aceb6c77af74 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Fri, 16 Jun 2023 11:32:55 +0300 Subject: [PATCH 25/31] Fix receipts --- src/Nethermind/Nethermind.Evm/TransactionExtensions.cs | 2 +- .../TransactionProcessing/TransactionProcessor.cs | 2 +- src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs | 2 +- src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs index a905242f6ca..1b442bc078b 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs @@ -23,7 +23,7 @@ public static TxGasInfo GetGasInfo(this Transaction tx, bool is1559Enabled, Bloc if (tx.SupportsBlobs) { dataGas = DataGasCalculator.CalculateDataGas(tx); - dataGasPrice = DataGasCalculator.CalculateDataGasPrice(header, tx); + dataGasPrice = DataGasCalculator.CalculateDataGasPricePerUnit(header); } return new(effectiveGasPrice, dataGasPrice, dataGas); diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 5e49fecb240..5dbf8aef2b2 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -278,7 +278,7 @@ private void Execute(Transaction transaction, BlockHeader block, ITxTracer txTra TraceLogInvalidTx(transaction, $"INSUFFICIENT_MAX_FEE_PER_DATA_GAS_FOR_SENDER_BALANCE: ({caller})_BALANCE = {senderBalance}, MAX_FEE_PER_GAS: {transaction.MaxFeePerGas}, MAX_FEE_PER_DATA_GAS: {transaction.MaxFeePerDataGas}"); QuickFail(transaction, block, txTracer, eip658NotEnabled, - "insufficient MaxFeePerGas for sender balance"); + "insufficient MaxFeePerDataGas for sender balance"); return; } } diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index 4dba1905c19..0752d82f079 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -271,7 +271,7 @@ public void GetReceiptAndGasInfo_returns_correct_results(bool isCanonical, bool _receiptStorage.Get(block).Returns(new[] { receipt }); (TxReceipt? Receipt, TxGasInfo? GasInfo, int LogIndexStart) result = postEip4844 - ? (receipt, new(effectiveGasPrice, 262144, 262144), 0) + ? (receipt, new(effectiveGasPrice, 1, 262144), 0) : (receipt, new(effectiveGasPrice), 0); if (!isCanonical) diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs index 7ce43ff3411..d571e1c2194 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/ReceiptForRpc.cs @@ -44,8 +44,10 @@ public ReceiptForRpc(Keccak txHash, TxReceipt receipt, TxGasInfo gasInfo, int lo public long BlockNumber { get; set; } public long CumulativeGasUsed { get; set; } public long GasUsed { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public ulong? DataGasUsed { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public UInt256? DataGasPrice { get; set; } From 8c2dc1da566b4cd578aa75a5ce36e3cd21109af6 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 19 Jun 2023 16:58:28 +0300 Subject: [PATCH 26/31] Add overflow checks --- .../Producers/TxPoolTxSource.cs | 18 +++++- .../Validators/BlockValidator.cs | 14 ++++- .../DataGasCalculatorTests.cs | 26 ++++++-- .../Nethermind.Evm/DataGasCalculator.cs | 63 ++++++++++++------- .../Nethermind.Evm/TransactionExtensions.cs | 15 +++-- .../TransactionProcessor.cs | 10 +-- 6 files changed, 101 insertions(+), 45 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index d26c9390ad4..64099a4794f 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -61,7 +61,7 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi // TODO: removing transactions from TX pool here seems to be a bad practice since they will // not come back if the block is ignored? int blobsCounter = 0; - UInt256? dataGasPrice = null; + UInt256 dataGasPrice = UInt256.Zero; foreach (Transaction tx in transactions) { @@ -79,8 +79,20 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi if (tx.SupportsBlobs) { - dataGasPrice ??= DataGasCalculator.CalculateDataGasPricePerUnit( - DataGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()) ?? 0); + if (dataGasPrice == UInt256.Zero) + { + ulong? excessDataGas = DataGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()); + if (excessDataGas is null) + { + if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, the specification is not configured to handle shard blob transactions."); + continue; + } + if (!DataGasCalculator.TryCalculateDataGasPricePerUnit(excessDataGas.Value, out dataGasPrice)) + { + if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, failed to calculate data gas price."); + continue; + } + } int txAmountOfBlobs = tx.BlobVersionedHashes?.Length ?? 0; diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 55ea2a3cd88..4b3fb7b393a 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -215,7 +215,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str } int blobsInBlock = 0; - UInt256? dataGasPrice = null; + UInt256 dataGasPrice = UInt256.Zero; for (int txIndex = 0; txIndex < block.Transactions.Length; txIndex++) { Transaction transaction = block.Transactions[txIndex]; @@ -223,8 +223,16 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str { continue; } - - if (transaction.MaxFeePerDataGas < (dataGasPrice ??= DataGasCalculator.CalculateDataGasPricePerUnit(block.Header))) + if (dataGasPrice == UInt256.Zero) + { + if (!DataGasCalculator.TryCalculateDataGasPricePerUnit(block.Header, out dataGasPrice)) + { + error = $"{nameof(dataGasPrice)} overflow."; + if (_logger.IsWarn) _logger.Warn(error); + return false; + } + } + if (transaction.MaxFeePerDataGas < dataGasPrice) { error = $"A transaction has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; if (_logger.IsWarn) _logger.Warn(error); diff --git a/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs index 901fd7abae2..3490bf44bde 100644 --- a/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/DataGasCalculatorTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; @@ -23,8 +22,8 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) BlockHeader parentHeader = Build.A.BlockHeader .WithDataGasUsed(DataGasCalculator.CalculateDataGas(testCase.parentBlobsCount)) .WithExcessDataGas(testCase.parentExcessDataGas).TestObject; - DataGasCalculator.CalculateExcessDataGas(parentHeader, spec).Should() - .Be(areBlobsEnabled ? testCase.expectedExcessDataGas : null); + + Assert.That(DataGasCalculator.CalculateExcessDataGas(parentHeader, spec), Is.EqualTo(areBlobsEnabled ? testCase.expectedExcessDataGas : null)); } Test(Homestead.Instance, false); @@ -43,12 +42,27 @@ void Test(IReleaseSpec spec, bool areBlobsEnabled) } [TestCaseSource(nameof(BlobDataGasCostTestCaseSource))] - public void Data_gas_cost_is_calculated_properly( + public void Data_gas_price_is_calculated_properly( (Transaction tx, ulong excessDataGas, UInt256 expectedCost) testCase) { BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(testCase.excessDataGas).TestObject; - DataGasCalculator.CalculateDataGasPrice(header, testCase.tx).Should() - .Be(testCase.expectedCost); + + bool success = DataGasCalculator.TryCalculateDataGasPrice(header, testCase.tx, out UInt256 dataGasPrice); + + Assert.That(success, Is.True); + Assert.That(dataGasPrice, Is.EqualTo(testCase.expectedCost)); + } + + [Test] + public void Data_gas_price_may_overflow() + { + var tx = Build.A.Transaction.WithType(TxType.Blob).WithBlobVersionedHashes(1000).TestObject; + BlockHeader header = Build.A.BlockHeader.WithExcessDataGas(ulong.MaxValue).TestObject; + + bool success = DataGasCalculator.TryCalculateDataGasPrice(header, tx, out UInt256 dataGasPrice); + + Assert.That(success, Is.False); + Assert.That(dataGasPrice, Is.EqualTo(UInt256.MaxValue)); } public static IEnumerable<(ulong parentExcessDataGas, int parentBlobsCount, ulong expectedExcessDataGas)> ExcessDataGasTestCaseSource() diff --git a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs index 346d3743ea7..db3ec755ab4 100644 --- a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs @@ -16,35 +16,61 @@ public static ulong CalculateDataGas(int blobCount) => public static ulong CalculateDataGas(Transaction transaction) => CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); - public static UInt256 CalculateDataGasPrice(BlockHeader header, Transaction transaction) => - CalculateDataGas(transaction) * CalculateDataGasPricePerUnit(header); + public static bool TryCalculateDataGasPrice(BlockHeader header, Transaction transaction, out UInt256 dataGasPrice) + { + if (!TryCalculateDataGasPricePerUnit(header.ExcessDataGas.Value, out UInt256 dataGasPricePerUnit)) + { + dataGasPrice = UInt256.MaxValue; + return false; + } + return !UInt256.MultiplyOverflow(CalculateDataGas(transaction), dataGasPricePerUnit, out dataGasPrice); + } - public static UInt256 CalculateDataGasPricePerUnit(BlockHeader header) => + public static bool TryCalculateDataGasPricePerUnit(BlockHeader header, out UInt256 dataGasPricePerUnit) => header.ExcessDataGas is null ? throw new ArgumentException(nameof(BlockHeader.ExcessDataGas)) - : CalculateDataGasPricePerUnit(header.ExcessDataGas.Value); + : TryCalculateDataGasPricePerUnit(header.ExcessDataGas.Value, out dataGasPricePerUnit); - public static UInt256 CalculateDataGasPricePerUnit(ulong excessDataGas) + public static bool TryCalculateDataGasPricePerUnit(ulong excessDataGas, out UInt256 dataGasPricePerUnit) { - static UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) + static bool FakeExponentialOverflow(UInt256 factor, UInt256 num, UInt256 denominator, out UInt256 dataGasPricePerUnit) { UInt256 output = UInt256.Zero; - UInt256 numAccum = factor * denominator; + if (UInt256.MultiplyOverflow(factor, denominator, out UInt256 numAccum)) + { + dataGasPricePerUnit = UInt256.MaxValue; + return true; + } for (UInt256 i = 1; numAccum > 0; i++) { - output += numAccum; - numAccum *= num; - numAccum /= i * denominator; + if (UInt256.AddOverflow(output, numAccum, out output)) + { + dataGasPricePerUnit = UInt256.MaxValue; + return true; + } + + if (UInt256.MultiplyOverflow(numAccum, num, out UInt256 updatedNumAccum)) + { + dataGasPricePerUnit = UInt256.MaxValue; + return true; + } + + if (UInt256.MultiplyOverflow(i, denominator, out UInt256 multipliedDeniminator)) + { + dataGasPricePerUnit = UInt256.MaxValue; + return true; + } + + numAccum = updatedNumAccum / multipliedDeniminator; } - return output / denominator; + dataGasPricePerUnit = output / denominator; + return false; } - UInt256 scaleDueToParentExcessDataGas = - FakeExponential(Eip4844Constants.MinDataGasPrice, excessDataGas, Eip4844Constants.DataGasUpdateFraction); - return scaleDueToParentExcessDataGas; + return !FakeExponentialOverflow(Eip4844Constants.MinDataGasPrice, excessDataGas, Eip4844Constants.DataGasUpdateFraction, out dataGasPricePerUnit); } public static ulong? CalculateExcessDataGas(BlockHeader? parentBlockHeader, IReleaseSpec releaseSpec) @@ -65,13 +91,4 @@ static UInt256 FakeExponential(UInt256 factor, UInt256 num, UInt256 denominator) ? 0 : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); } - - public static ulong? CalculateExcessDataGas(ulong? parentExcessDataGas, ulong? parentDataGasUsed) - { - ulong excessDataGas = parentExcessDataGas ?? 0; - excessDataGas += parentDataGasUsed ?? 0; - return excessDataGas < Eip4844Constants.TargetDataGasPerBlock - ? 0 - : (excessDataGas - Eip4844Constants.TargetDataGasPerBlock); - } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs index 1b442bc078b..1a5b800f7e0 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionExtensions.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using Nethermind.Core; using Nethermind.Int256; @@ -18,15 +19,19 @@ tx.To is not null public static TxGasInfo GetGasInfo(this Transaction tx, bool is1559Enabled, BlockHeader header) { UInt256 effectiveGasPrice = tx.CalculateEffectiveGasPrice(is1559Enabled, header.BaseFeePerGas); - ulong? dataGas = null; - UInt256? dataGasPrice = null; + if (tx.SupportsBlobs) { - dataGas = DataGasCalculator.CalculateDataGas(tx); - dataGasPrice = DataGasCalculator.CalculateDataGasPricePerUnit(header); + if (!DataGasCalculator.TryCalculateDataGasPricePerUnit(header, out UInt256 dataGasPrice)) + { + throw new ArgumentException(nameof(dataGasPrice)); + } + ulong dataGas = DataGasCalculator.CalculateDataGas(tx); + + return new(effectiveGasPrice, dataGasPrice, dataGas); } - return new(effectiveGasPrice, dataGasPrice, dataGas); + return new(effectiveGasPrice, null, null); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 6bd688db622..5a98a060df4 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -2,11 +2,9 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Data.Common; using System.IO; using System.Linq; using System.Runtime.CompilerServices; -using System.Transactions; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -19,7 +17,6 @@ using Nethermind.State; using Nethermind.State.Tracing; using static Nethermind.Core.Extensions.MemoryExtensions; -using Transaction = Nethermind.Core.Transaction; namespace Nethermind.Evm.TransactionProcessing { @@ -395,8 +392,11 @@ private bool BuyGas(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTr overflows = UInt256.MultiplyOverflow((UInt256)tx.GasLimit, effectiveGasPrice, out senderReservedGasPayment); if (!overflows && tx.SupportsBlobs) { - UInt256 dataGasFee = tx.SupportsBlobs ? DataGasCalculator.CalculateDataGasPrice(header, tx) : UInt256.Zero; - overflows = UInt256.AddOverflow(senderReservedGasPayment, dataGasFee, out senderReservedGasPayment); + overflows = !DataGasCalculator.TryCalculateDataGasPrice(header, tx, out UInt256 dataGasFee); + if (!overflows) + { + overflows = UInt256.AddOverflow(senderReservedGasPayment, dataGasFee, out senderReservedGasPayment); + } } if (overflows || senderReservedGasPayment > balanceLeft) From 8a73222e4b00a4b494f7dc5025f6457f4536c24a Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Mon, 19 Jun 2023 19:31:36 +0300 Subject: [PATCH 27/31] Fix tests --- .../TransactionSelectorTests.cs | 20 +++++++++++++++---- .../Producers/TxPoolTxSource.cs | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs index a734d5ca1bb..2bdf521fd74 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs @@ -151,11 +151,14 @@ 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.MaxDataGasPerTransaction / Eip4844Constants.DataGasPerBlob - 1][]; @@ -164,14 +167,19 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases 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.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( @@ -241,9 +249,13 @@ void SetAccountStates(IEnumerable
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 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()); diff --git a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs index 64099a4794f..ae5ef686772 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/TxPoolTxSource.cs @@ -81,7 +81,7 @@ public IEnumerable GetTransactions(BlockHeader parent, long gasLimi { if (dataGasPrice == UInt256.Zero) { - ulong? excessDataGas = DataGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetFinalSpec()); + ulong? excessDataGas = DataGasCalculator.CalculateExcessDataGas(parent, _specProvider.GetSpec(parent)); if (excessDataGas is null) { if (_logger.IsTrace) _logger.Trace($"Declining {tx.ToShortString()}, the specification is not configured to handle shard blob transactions."); From c30770334111058027d3326d47c8c3f70e2277b3 Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Thu, 22 Jun 2023 20:41:57 +0300 Subject: [PATCH 28/31] Fix encoding; improve text; clean up --- .../Processing/BlockProcessor.cs | 3 +-- .../Producers/BlockProducerBase.cs | 1 - .../Validators/BlockValidator.cs | 6 ++---- src/Nethermind/Nethermind.Evm/DataGasCalculator.cs | 14 ++++++++++++++ .../Nethermind.Serialization.Rlp/HeaderDecoder.cs | 4 ++-- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index d1eb8b3ae03..7ff421dc73c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -229,8 +229,7 @@ protected virtual TxReceipt[] ProcessBlock( if (spec.IsEip4844Enabled) { - block.Header.DataGasUsed = DataGasCalculator.CalculateDataGas( - block.Transactions.Sum(tx => tx.BlobVersionedHashes?.Length ?? 0)); + block.Header.DataGasUsed = DataGasCalculator.CalculateDataGas(block.Transactions); } block.Header.ReceiptsRoot = receipts.GetReceiptsRoot(spec, block.ReceiptsRoot); diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs index 6899d80e8ab..d4e5accf15e 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerBase.cs @@ -300,7 +300,6 @@ protected virtual BlockHeader PrepareBlockHeader(BlockHeader parent, if (Logger.IsDebug) Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}."); - IReleaseSpec spec = _specProvider.GetSpec(header); header.BaseFeePerGas = BaseFeeCalculator.Calculate(parent, _specProvider.GetSpec(header)); return header; diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 4b3fb7b393a..6443e1bd3fd 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -2,9 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Linq; using Nethermind.Blockchain; -using Nethermind.Blockchain.Find; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -234,7 +232,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str } if (transaction.MaxFeePerDataGas < dataGasPrice) { - error = $"A transaction has unsufficient MaxFeePerDataGas {transaction.MaxFeePerDataGas} < {dataGasPrice}."; + error = $"A transaction has unsufficient {nameof(transaction.MaxFeePerDataGas)} to cover current data gas fee: {transaction.MaxFeePerDataGas} < {dataGasPrice}."; if (_logger.IsWarn) _logger.Warn(error); return false; } @@ -252,7 +250,7 @@ private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out str if (dataGasUsed != block.Header.DataGasUsed) { - error = $"DataGasUsed does not match actual data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; + error = $"{nameof(BlockHeader.DataGasUsed)} declared in the block header does not match actual data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; if (_logger.IsWarn) _logger.Warn(error); return false; } diff --git a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs index db3ec755ab4..444b695f8e2 100644 --- a/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/DataGasCalculator.cs @@ -16,6 +16,20 @@ public static ulong CalculateDataGas(int blobCount) => public static ulong CalculateDataGas(Transaction transaction) => CalculateDataGas(transaction.BlobVersionedHashes?.Length ?? 0); + public static ulong CalculateDataGas(Transaction[] transactions) + { + int blobCount = 0; + foreach (Transaction tx in transactions) + { + if (tx.SupportsBlobs) + { + blobCount += tx.BlobVersionedHashes!.Length; + } + } + + return CalculateDataGas(blobCount); + } + public static bool TryCalculateDataGasPrice(BlockHeader header, Transaction transaction, out UInt256 dataGasPrice) { if (!TryCalculateDataGasPricePerUnit(header.ExcessDataGas.Value, out UInt256 dataGasPricePerUnit)) diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs index d6d1ef9fa62..057e70c4c9b 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/HeaderDecoder.cs @@ -79,8 +79,8 @@ public class HeaderDecoder : IRlpValueDecoder, IRlpStreamDecoder Date: Thu, 29 Jun 2023 13:09:16 +0300 Subject: [PATCH 29/31] Add gas fields to the local 4844 network genesis --- src/Nethermind/Chains/eip4844_local.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Chains/eip4844_local.json b/src/Nethermind/Chains/eip4844_local.json index 5c4844d4f6f..b42da9d106e 100644 --- a/src/Nethermind/Chains/eip4844_local.json +++ b/src/Nethermind/Chains/eip4844_local.json @@ -56,7 +56,9 @@ } }, "timestamp": 0, - "baseFeePerGas": "0x7" + "baseFeePerGas": "0x7", + "dataGasUsed": "0x0", + "excessDataGas": "0x0" }, "accounts": { "0x8A04d14125D0FDCDc742F4A05C051De07232EDa4": { From 2a66fb5dae50a5e0431061d530bdd7798f7d230c Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Fri, 30 Jun 2023 14:40:30 +0300 Subject: [PATCH 30/31] Refactor BlockValidator --- .../Validators/BlockValidator.cs | 61 ++++++++++++------- .../BlockProduction/PostMergeBlockProducer.cs | 3 - 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 6443e1bd3fd..5c0bf211ccf 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -55,16 +55,18 @@ public bool Validate(BlockHeader header, bool isUncle) /// public bool ValidateSuggestedBlock(Block block) { - Transaction[] txs = block.Transactions; IReleaseSpec spec = _specProvider.GetSpec(block.Header); - for (int i = 0; i < txs.Length; i++) + if (!ValidateTransactions(block, spec, out int blobsInBlock, out string error)) { - if (!_txValidator.IsWellFormed(txs[i], spec)) - { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid transaction {txs[i].Hash}"); - return false; - } + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}"); + return false; + } + + if (!ValidateDataGasUsed(block, spec, blobsInBlock, out string dataGasError)) + { + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {dataGasError}"); + return false; } if (spec.MaximumUncleCount < block.Uncles.Length) @@ -101,9 +103,6 @@ public bool ValidateSuggestedBlock(Block block) if (!ValidateWithdrawals(block, spec, out _)) return false; - if (!ValidateTransactionsDataGas(block, spec, out _)) - return false; - return true; } @@ -204,54 +203,70 @@ private bool ValidateWithdrawals(Block block, IReleaseSpec spec, out string? err return true; } - private bool ValidateTransactionsDataGas(Block block, IReleaseSpec spec, out string? error) + private bool ValidateTransactions(Block block, IReleaseSpec spec, out int blobsInBlock, out string? error) { - if (!spec.IsEip4844Enabled) - { - error = null; - return true; - } + blobsInBlock = 0; - int blobsInBlock = 0; UInt256 dataGasPrice = UInt256.Zero; - for (int txIndex = 0; txIndex < block.Transactions.Length; txIndex++) + + Transaction[] transactions = block.Transactions; + + for (int txIndex = 0; txIndex < transactions.Length; txIndex++) { - Transaction transaction = block.Transactions[txIndex]; + Transaction transaction = transactions[txIndex]; + + if (!_txValidator.IsWellFormed(transaction, spec)) + { + error = $"{Invalid(block)} Invalid transaction {transaction.Hash}"; + return false; + } + if (!transaction.SupportsBlobs) { continue; } + if (dataGasPrice == UInt256.Zero) { if (!DataGasCalculator.TryCalculateDataGasPricePerUnit(block.Header, out dataGasPrice)) { error = $"{nameof(dataGasPrice)} overflow."; - if (_logger.IsWarn) _logger.Warn(error); return false; } } + if (transaction.MaxFeePerDataGas < dataGasPrice) { error = $"A transaction has unsufficient {nameof(transaction.MaxFeePerDataGas)} to cover current data gas fee: {transaction.MaxFeePerDataGas} < {dataGasPrice}."; - if (_logger.IsWarn) _logger.Warn(error); return false; } blobsInBlock += transaction.BlobVersionedHashes!.Length; } + error = null; + return true; + } + + private bool ValidateDataGasUsed(Block block, IReleaseSpec spec, in int blobsInBlock, out string? error) + { + if (!spec.IsEip4844Enabled) + { + error = null; + return true; + } + ulong dataGasUsed = DataGasCalculator.CalculateDataGas(blobsInBlock); + if (dataGasUsed > Eip4844Constants.MaxDataGasPerBlock) { error = $"A block cannot have more than {Eip4844Constants.MaxDataGasPerBlock} data gas."; - if (_logger.IsWarn) _logger.Warn(error); return false; } if (dataGasUsed != block.Header.DataGasUsed) { error = $"{nameof(BlockHeader.DataGasUsed)} declared in the block header does not match actual data gas used: {block.Header.DataGasUsed} != {dataGasUsed}."; - if (_logger.IsWarn) _logger.Warn(error); return false; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs index df8bc662810..6bc92ec14c2 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/BlockProduction/PostMergeBlockProducer.cs @@ -11,9 +11,6 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; -using Nethermind.Crypto; -using Nethermind.Core.Extensions; -using System.Threading; using Nethermind.Logging; using Nethermind.State; using Nethermind.Evm; From fbdf0a9800030de6a5a2ce3187d440434893447f Mon Sep 17 00:00:00 2001 From: Alexey Osipov Date: Fri, 30 Jun 2023 15:55:49 +0300 Subject: [PATCH 31/31] Add additional check --- ...Processor.BlockProductionTransactionPicker.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs index f5a2e6bc030..48c14c7c03f 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionPicker.cs @@ -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 @@ -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 && ( + !DataGasCalculator.TryCalculateDataGasPrice(block.Header, transaction, out UInt256 dataGasPrice) || + senderBalance < (maxFee = (UInt256)transaction.GasLimit * transaction.MaxFeePerGas + dataGasPrice + transaction.Value))) { - 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; }