diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 00000000000..b5c7b5616f1 --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,46 @@ +name: Trivy scanner + +on: + pull_request: + branches: [master] + push: + branches: [master] + schedule: + - cron: '29 19 * * 4' + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + name: Build + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read + env: + IMAGE_TAG: nethermind:${{ github.sha }} + steps: + - name: Check out repository + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1 + + - name: Build Docker image + run: docker build -t $IMAGE_TAG . + + - name: Scan + uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2 #v0.28.0 + with: + image-ref: ${{ env.IMAGE_TAG }} + format: template + template: '@/contrib/sarif.tpl' + output: trivy-results.sarif + severity: CRITICAL,HIGH + env: + TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db + + - name: Upload scan results + uses: github/codeql-action/upload-sarif@cf5b0a9041d3c1d336516f1944c96d96598193cc #v2.19.1 + with: + sarif_file: trivy-results.sarif diff --git a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs index fe5fb25c019..66df7e618ee 100644 --- a/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs @@ -171,7 +171,7 @@ protected async Task RunTest(BlockchainTest test, Stopwatch? stateProvider, receiptStorage, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), new BlockhashStore(specProvider, stateProvider), _logManager); diff --git a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs index 5ca0f63f74d..2da9aabbc1c 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/AuraBlockProcessorTests.cs @@ -158,7 +158,7 @@ void Process(AuRaBlockProcessor auRaBlockProcessor, int blockNumber, Hash256 sta new BlockProcessor.BlockValidationTransactionsExecutor(transactionProcessor, stateProvider), stateProvider, NullReceiptStorage.Instance, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), LimboLogs.Instance, Substitute.For(), new WithdrawalProcessor(stateProvider, LimboLogs.Instance), diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs index bcbe3b8be48..6f2f7b13d6d 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/AuRaContractGasLimitOverrideTests.cs @@ -97,7 +97,7 @@ protected override BlockProcessor CreateBlockProcessor() new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State), State, ReceiptStorage, - new BeaconBlockRootHandler(TxProcessor), + new BeaconBlockRootHandler(TxProcessor, State), LimboLogs.Instance, BlockTree, NullWithdrawalProcessor.Instance, diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs index c754ce285f8..cda399944da 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxCertifierFilterTests.cs @@ -154,7 +154,7 @@ protected override BlockProcessor CreateBlockProcessor() new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State), State, ReceiptStorage, - new BeaconBlockRootHandler(TxProcessor), + new BeaconBlockRootHandler(TxProcessor, State), LimboLogs.Instance, BlockTree, NullWithdrawalProcessor.Instance, diff --git a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs index de6de6eb464..da04745095f 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Transactions/TxPermissionFilterTest.cs @@ -296,7 +296,7 @@ protected override BlockProcessor CreateBlockProcessor() new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State), State, ReceiptStorage, - new BeaconBlockRootHandler(TxProcessor), + new BeaconBlockRootHandler(TxProcessor, State), LimboLogs.Instance, BlockTree, NullWithdrawalProcessor.Instance, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BeaconBlockRootHandlerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BeaconBlockRootHandlerTests.cs new file mode 100644 index 00000000000..8f3e5461c7d --- /dev/null +++ b/src/Nethermind/Nethermind.Blockchain.Test/BeaconBlockRootHandlerTests.cs @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain.BeaconBlockRoot; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Eip2930; +using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; +using Nethermind.Evm; +using Nethermind.Evm.Tracing; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.Int256; +using Nethermind.Specs.Forks; +using Nethermind.State; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Blockchain.Test; + +public class BeaconBlockRootHandlerTests +{ + private BeaconBlockRootHandler _beaconBlockRootHandler; + private ITransactionProcessor _transactionProcessor; + private IWorldState _worldState; + + [SetUp] + public void Setup() + { + _worldState = Substitute.For(); + _transactionProcessor = Substitute.For(); + _beaconBlockRootHandler = new BeaconBlockRootHandler(_transactionProcessor, _worldState); + } + + [Test] + public void Test_BeaconRootsAccessList_IsBeaconBlockRootAvailableFalse() + { + BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithParentBeaconBlockRoot(Hash256.Zero).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(true); + + (Address? toAddress, AccessList? accessList) result = _beaconBlockRootHandler + .BeaconRootsAccessList(block, Shanghai.Instance); + + Assert.That(result.accessList, Is.Null); + Assert.That(result.toAddress, Is.Null); + } + + [Test] + public void Test_BeaconRootsAccessList_HeaderIsGenesis() + { + BlockHeader header = Build.A.BlockHeader.WithParentBeaconBlockRoot(Hash256.Zero).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(true); + + (Address? toAddress, AccessList? accessList) result = _beaconBlockRootHandler + .BeaconRootsAccessList(block, Cancun.Instance); + + Assert.That(result.accessList, Is.Null); + Assert.That(result.toAddress, Is.Null); + } + + [Test] + public void Test_BeaconRootsAccessList_ParentBeaconBlockRootIsNull() + { + BlockHeader header = Build.A.BlockHeader.WithNumber(1).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(true); + + (Address? toAddress, AccessList? accessList) result = _beaconBlockRootHandler + .BeaconRootsAccessList(block, Cancun.Instance); + + Assert.That(result.accessList, Is.Null); + Assert.That(result.toAddress, Is.Null); + } + + [Test] + public void Test_BeaconRootsAccessList_canInsertBeaconRootIsTrue_AccountNotExist() + { + BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithParentBeaconBlockRoot(Hash256.Zero).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(false); + + (Address? toAddress, AccessList? accessList) result = _beaconBlockRootHandler + .BeaconRootsAccessList(block, Cancun.Instance); + + Assert.That(result.accessList, Is.Null); + Assert.That(result.toAddress, Is.Null); + } + + [Test] + public void Test_BeaconRootsAccessList_canInsertBeaconRootIsTrue_AccountExists() + { + BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithParentBeaconBlockRoot(Hash256.Zero).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(true); + + (Address? toAddress, AccessList? accessList) result = _beaconBlockRootHandler + .BeaconRootsAccessList(block, Cancun.Instance); + + Assert.That(result.accessList, Is.Not.Null); + Assert.That(result.accessList.Count.AddressesCount, Is.EqualTo(1)); + Assert.That(result.accessList.Count.StorageKeysCount, Is.EqualTo(1)); + } + + [Test] + public void Test_BeaconRootsAccessList_canInsertBeaconRootIsTrue_AccountExists_IncludeStorageCellsIsFalse() + { + BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithParentBeaconBlockRoot(Hash256.Zero).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(true); + + (Address? toAddress, AccessList? accessList) result = _beaconBlockRootHandler + .BeaconRootsAccessList(block, Cancun.Instance, false); + + Assert.That(result.accessList, Is.Not.Null); + Assert.That(result.accessList.Count.AddressesCount, Is.EqualTo(1)); + Assert.That(result.accessList.Count.StorageKeysCount, Is.EqualTo(0)); + } + + [Test] + public void Test_StoreBeaconRoot_AccessListIsNull() + { + BlockHeader header = Build.A.BlockHeader.TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + + _beaconBlockRootHandler.StoreBeaconRoot(block, Cancun.Instance); + + _transactionProcessor.DidNotReceive().Execute(Arg.Any(), Arg.Any(), Arg.Any()); + } + + [Test] + public void Test_StoreBeaconRoot_AccessListNotNull() + { + BlockHeader header = Build.A.BlockHeader.WithNumber(1).WithParentBeaconBlockRoot(Hash256.Zero).TestObject; + Block block = Build.A.Block.WithHeader(header).TestObject; + _worldState.AccountExists(Arg.Any
()).Returns(true); + + _beaconBlockRootHandler.StoreBeaconRoot(block, Cancun.Instance); + + Transaction transaction = new() + { + Value = UInt256.Zero, + Data = header.ParentBeaconBlockRoot!.Bytes.ToArray(), + To = Eip4788Constants.BeaconRootsAddress, + SenderAddress = Address.SystemUser, + GasLimit = 30_000_000L, + GasPrice = UInt256.Zero, + AccessList = new AccessList.Builder().AddAddress(Eip4788Constants.BeaconRootsAddress).Build() + }; + + transaction.Hash = transaction.CalculateHash(); + _transactionProcessor.Received().Execute(Arg.Is(t => + t.Hash == transaction.Hash), header, NullTxTracer.Instance); + } +} diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs index 60c7c37b66e..a9c11d23a2d 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs @@ -50,7 +50,7 @@ public void Prepared_block_contains_author_field() stateProvider, NullReceiptStorage.Instance, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), Substitute.For(), LimboLogs.Instance); @@ -81,7 +81,7 @@ public void Recovers_state_on_cancel() stateProvider, NullReceiptStorage.Instance, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), Substitute.For(), LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs index 096dcd6db9a..1453c55dadd 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs @@ -76,7 +76,7 @@ public void Test() stateProvider, NullReceiptStorage.Instance, txProcessor, - new BeaconBlockRootHandler(txProcessor), + new BeaconBlockRootHandler(txProcessor, stateProvider), new BlockhashStore(specProvider, stateProvider), LimboLogs.Instance); BlockchainProcessor blockchainProcessor = new( diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index 88274cfd17b..0f87b9ea846 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -78,7 +78,7 @@ public void Setup() stateProvider, NullReceiptStorage.Instance, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), new BlockhashStore(MainnetSpecProvider.Instance, stateProvider), LimboLogs.Instance); _blockchainProcessor = new BlockchainProcessor( diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs index c464091ba49..a9a519e4492 100644 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs +++ b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Core.Specs; @@ -9,9 +8,10 @@ using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; +using Nethermind.State; namespace Nethermind.Blockchain.BeaconBlockRoot; -public class BeaconBlockRootHandler(ITransactionProcessor processor) : IBeaconBlockRootHandler +public class BeaconBlockRootHandler(ITransactionProcessor processor, IWorldState stateProvider) : IBeaconBlockRootHandler { private const long GasLimit = 30_000_000L; @@ -26,7 +26,7 @@ public class BeaconBlockRootHandler(ITransactionProcessor processor) : IBeaconBl spec.Eip4788ContractAddress ?? Eip4788Constants.BeaconRootsAddress : null; - if (eip4788ContractAddress is null) + if (eip4788ContractAddress is null || !stateProvider.AccountExists(eip4788ContractAddress)) { return (null, null); } diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs index d6e3ec0f5ed..05aea2133ea 100644 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs +++ b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/IBeaconBlockRootHandler.cs @@ -4,6 +4,7 @@ using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Core.Specs; +using Nethermind.State; namespace Nethermind.Blockchain.BeaconBlockRoot; public interface IBeaconBlockRootHandler diff --git a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs index 83e2f3b5372..1a56439105b 100644 --- a/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs +++ b/src/Nethermind/Nethermind.Clique.Test/CliqueBlockProducerTests.cs @@ -140,7 +140,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f stateProvider, NullReceiptStorage.Instance, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), new BlockhashStore(goerliSpecProvider, stateProvider), nodeLogManager); @@ -161,7 +161,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f minerStateProvider, NullReceiptStorage.Instance, minerTransactionProcessor, - new BeaconBlockRootHandler(minerTransactionProcessor), + new BeaconBlockRootHandler(minerTransactionProcessor, minerStateProvider), new BlockhashStore(goerliSpecProvider, minerStateProvider), nodeLogManager); diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs index d2a3952e8f0..cf7ac81bbc7 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/InitializeBlockchainAuRa.cs @@ -108,7 +108,7 @@ protected virtual AuRaBlockProcessor NewAuraBlockProcessor(ITxFilter txFilter, B new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor, worldState), worldState, _api.ReceiptStorage!, - new BeaconBlockRootHandler(_api.TransactionProcessor!), + new BeaconBlockRootHandler(_api.TransactionProcessor!, worldState), _api.LogManager, _api.BlockTree!, NullWithdrawalProcessor.Instance, diff --git a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs index 5fa09b539d8..2b3d2d5578e 100644 --- a/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs +++ b/src/Nethermind/Nethermind.Consensus.AuRa/InitializationSteps/StartBlockProducerAuRa.cs @@ -155,7 +155,7 @@ private BlockProcessor CreateBlockProcessor(IReadOnlyTxProcessingScope changeabl _api.BlockProducerEnvFactory.TransactionsExecutorFactory.Create(changeableTxProcessingEnv), changeableTxProcessingEnv.WorldState, _api.ReceiptStorage, - new BeaconBlockRootHandler(changeableTxProcessingEnv.TransactionProcessor), + new BeaconBlockRootHandler(changeableTxProcessingEnv.TransactionProcessor, changeableTxProcessingEnv.WorldState), _api.LogManager, _api.BlockTree, NullWithdrawalProcessor.Instance, diff --git a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs index 9167e80f900..153a2941487 100644 --- a/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Clique/CliquePlugin.cs @@ -113,7 +113,7 @@ public IBlockProducer InitBlockProducer(ITxSource? additionalTxSource = null) scope.WorldState, NullReceiptStorage.Instance, getFromApi.TransactionProcessor, - new BeaconBlockRootHandler(scope.TransactionProcessor), + new BeaconBlockRootHandler(scope.TransactionProcessor, scope.WorldState), new BlockhashStore(getFromApi.SpecProvider, scope.WorldState), getFromApi.LogManager, new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(scope.WorldState, getFromApi.LogManager))); diff --git a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs index 215ae44e976..7c1be4c3c90 100644 --- a/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs +++ b/src/Nethermind/Nethermind.Consensus.Ethash/NethDevPlugin.cs @@ -83,7 +83,7 @@ public IBlockProducer InitBlockProducer(ITxSource? additionalTxSource = null) scope.WorldState, NullReceiptStorage.Instance, scope.TransactionProcessor, - new BeaconBlockRootHandler(scope.TransactionProcessor), + new BeaconBlockRootHandler(scope.TransactionProcessor, scope.WorldState), new BlockhashStore(getFromApi.SpecProvider, scope.WorldState), getFromApi.LogManager); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs index 0b278165205..97954e1ed5c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ReadOnlyChainProcessingEnv.cs @@ -69,7 +69,7 @@ IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor scope.WorldState, receiptStorage, scope.TransactionProcessor, - new BeaconBlockRootHandler(scope.TransactionProcessor), + new BeaconBlockRootHandler(scope.TransactionProcessor, scope.WorldState), new BlockhashStore(specProvider, scope.WorldState), logManager); } diff --git a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs index f896766bfbd..85e5697a8be 100644 --- a/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Consensus/Producers/BlockProducerEnvFactory.cs @@ -155,7 +155,7 @@ protected virtual BlockProcessor CreateBlockProcessor( readOnlyTxProcessingEnv.WorldState, receiptStorage, readOnlyTxProcessingEnv.TransactionProcessor, - new BeaconBlockRootHandler(readOnlyTxProcessingEnv.TransactionProcessor), + new BeaconBlockRootHandler(readOnlyTxProcessingEnv.TransactionProcessor, readOnlyTxProcessingEnv.WorldState), new BlockhashStore(_specProvider, readOnlyTxProcessingEnv.WorldState), logManager, new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(readOnlyTxProcessingEnv.WorldState, logManager)), diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 2af6892ee13..fb5118b4861 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -200,7 +200,7 @@ protected virtual async Task Build(ISpecProvider? specProvider = HeaderValidator = new HeaderValidator(BlockTree, Always.Valid, SpecProvider, LogManager); _canonicalityMonitor ??= new ReceiptCanonicalityMonitor(ReceiptStorage, LogManager); - BeaconBlockRootHandler = new BeaconBlockRootHandler(TxProcessor); + BeaconBlockRootHandler = new BeaconBlockRootHandler(TxProcessor, State); BlockValidator = new BlockValidator( new TxValidator(SpecProvider.ChainId), @@ -216,7 +216,6 @@ protected virtual async Task Build(ISpecProvider? specProvider = BloomStorage bloomStorage = new(new BloomConfig(), new MemDb(), new InMemoryDictionaryFileStoreFactory()); ReceiptsRecovery receiptsRecovery = new(new EthereumEcdsa(SpecProvider.ChainId), SpecProvider); LogFinder = new LogFinder(BlockTree, ReceiptStorage, ReceiptStorage, bloomStorage, LimboLogs.Instance, receiptsRecovery); - BeaconBlockRootHandler = new BeaconBlockRootHandler(TxProcessor); BlockProcessor = CreateBlockProcessor(); BlockchainProcessor chainProcessor = new(BlockTree, BlockProcessor, BlockPreprocessorStep, StateReader, LogManager, Consensus.Processing.BlockchainProcessor.Options.Default); @@ -390,7 +389,7 @@ protected virtual IBlockProcessor CreateBlockProcessor() => State, ReceiptStorage, TxProcessor, - new BeaconBlockRootHandler(TxProcessor), + new BeaconBlockRootHandler(TxProcessor, State), new BlockhashStore(SpecProvider, State), LogManager, preWarmer: CreateBlockCachePreWarmer(), diff --git a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs index 5196c1850ac..c86b147817e 100644 --- a/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Facade/Simulate/SimulateReadOnlyBlocksProcessingEnv.cs @@ -115,7 +115,7 @@ public IBlockProcessor GetProcessor(bool validate, UInt256? blobBaseFeeOverride) StateProvider, NullReceiptStorage.Instance, _transactionProcessor, - new BeaconBlockRootHandler(_transactionProcessor), + new BeaconBlockRootHandler(_transactionProcessor, StateProvider), new BlockhashStore(SpecProvider, StateProvider), _logManager); } diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 92aea789e83..630809f8b53 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -238,7 +238,7 @@ protected virtual BlockProcessor CreateBlockProcessor(BlockCachePreWarmer? preWa worldState, _api.ReceiptStorage, _api.TransactionProcessor, - new BeaconBlockRootHandler(_api.TransactionProcessor), + new BeaconBlockRootHandler(_api.TransactionProcessor, worldState), new BlockhashStore(_api.SpecProvider!, worldState), _api.LogManager, preWarmer: preWarmer diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index 885496c6812..02a8abacccd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -104,7 +104,7 @@ TransactionProcessor transactionProcessor stateProvider, NullReceiptStorage.Instance, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), new BlockhashStore(specProvider, stateProvider), LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index f9b10675107..1c4023f547f 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -73,7 +73,7 @@ public void Setup() stateProvider, NullReceiptStorage.Instance, transactionProcessor, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, stateProvider), new BlockhashStore(specProvider, stateProvider), LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index b2d1e4c26ab..663c941b485 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -153,7 +153,7 @@ protected override IBlockProcessor CreateBlockProcessor() State, ReceiptStorage, TxProcessor, - new BeaconBlockRootHandler(TxProcessor), + new BeaconBlockRootHandler(TxProcessor, State), new BlockhashStore(SpecProvider, State), LogManager, WithdrawalProcessor, diff --git a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs index 741930723bf..faf77f16d32 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/AuRaMergeBlockProducerEnvFactory.cs @@ -75,7 +75,7 @@ protected override BlockProcessor CreateBlockProcessor( TransactionsExecutorFactory.Create(readOnlyTxProcessingEnv), readOnlyTxProcessingEnv.WorldState, receiptStorage, - new BeaconBlockRootHandler(readOnlyTxProcessingEnv.TransactionProcessor), + new BeaconBlockRootHandler(readOnlyTxProcessingEnv.TransactionProcessor, readOnlyTxProcessingEnv.WorldState), logManager, _blockTree, new Consensus.Withdrawals.BlockProductionWithdrawalProcessor( diff --git a/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs b/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs index d37d4fb9b1a..6fec278699c 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa/InitializationSteps/InitializeBlockchainAuRaMerge.cs @@ -43,7 +43,7 @@ protected override AuRaBlockProcessor NewAuraBlockProcessor(ITxFilter txFilter, new BlockProcessor.BlockValidationTransactionsExecutor(transactionProcessor, worldState), worldState, _api.ReceiptStorage!, - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, worldState), _api.LogManager, _api.BlockTree!, new AuraWithdrawalProcessor(withdrawalContractFactory.Create(transactionProcessor), _api.LogManager), diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index 2de5457185a..abfce411741 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -153,7 +153,7 @@ private static ExecutionPayloadV4 CreateBlockRequestV4(MergeTestBlockchain chain ExecutionPayloadV4 blockRequestV4 = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot, requests: requests); blockRequestV4.TryGetBlock(out Block? block); - var beaconBlockRootHandler = new BeaconBlockRootHandler(chain.TxProcessor); + var beaconBlockRootHandler = new BeaconBlockRootHandler(chain.TxProcessor, chain.WorldStateManager.GlobalWorldState); beaconBlockRootHandler.StoreBeaconRoot(block!, chain.SpecProvider.GetSpec(block!.Header)); Snapshot before = chain.State.TakeSnapshot(); var blockHashStore = new BlockhashStore(chain.SpecProvider, chain.State); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index a95d1a9479b..cffbfafb516 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -255,7 +255,7 @@ protected override IBlockProcessor CreateBlockProcessor() State, ReceiptStorage, TxProcessor, - new BeaconBlockRootHandler(TxProcessor), + new BeaconBlockRootHandler(TxProcessor, State), new BlockhashStore(SpecProvider, State), LogManager, WithdrawalProcessor, diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs index c037fe6b16e..714a3999dcc 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs @@ -5,14 +5,13 @@ using DotNetty.Buffers; using Nethermind.Core; using Nethermind.Core.Buffers; -using Nethermind.Core.ConsensusRequests; using Nethermind.Serialization.Rlp; namespace Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages { public class BlockBodiesMessageSerializer : IZeroInnerMessageSerializer { - private readonly BlockBodyDecoder _blockBodyDecoder = new(); + private readonly BlockBodyDecoder _blockBodyDecoder = BlockBodyDecoder.Instance; public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message) { @@ -53,94 +52,5 @@ public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer) return new() { Bodies = new(bodies, memoryOwner) }; } - - private class BlockBodyDecoder : IRlpValueDecoder - { - private readonly TxDecoder _txDecoder = TxDecoder.Instance; - private readonly HeaderDecoder _headerDecoder = new(); - private readonly WithdrawalDecoder _withdrawalDecoderDecoder = new(); - private readonly ConsensusRequestDecoder _requestsDecoder = ConsensusRequestDecoder.Instance; - - public int GetLength(BlockBody item, RlpBehaviors rlpBehaviors) - { - return Rlp.LengthOfSequence(GetBodyLength(item)); - } - - public int GetBodyLength(BlockBody b) => - Rlp.LengthOfSequence(GetTxLength(b.Transactions)) + - Rlp.LengthOfSequence(GetUnclesLength(b.Uncles)) - + (b.Withdrawals is not null ? Rlp.LengthOfSequence(GetWithdrawalsLength(b.Withdrawals)) : 0) - + (b.Requests is not null ? Rlp.LengthOfSequence(GetRequestsLength(b.Requests)) : 0); - - private int GetTxLength(Transaction[] transactions) => transactions.Sum(t => _txDecoder.GetLength(t, RlpBehaviors.None)); - - private int GetUnclesLength(BlockHeader[] headers) => headers.Sum(t => _headerDecoder.GetLength(t, RlpBehaviors.None)); - - private int GetWithdrawalsLength(Withdrawal[] withdrawals) => withdrawals.Sum(t => _withdrawalDecoderDecoder.GetLength(t, RlpBehaviors.None)); - - private int GetRequestsLength(ConsensusRequest[] requests) => requests.Sum(t => _requestsDecoder.GetLength(t, RlpBehaviors.None)); - - public BlockBody? Decode(ref Rlp.ValueDecoderContext ctx, RlpBehaviors rlpBehaviors = RlpBehaviors.None) - { - int sequenceLength = ctx.ReadSequenceLength(); - int startingPosition = ctx.Position; - if (sequenceLength == 0) - { - return null; - } - - // quite significant allocations (>0.5%) here based on a sample 3M blocks sync - // (just on these delegates) - Transaction[] transactions = ctx.DecodeArray(_txDecoder); - BlockHeader[] uncles = ctx.DecodeArray(_headerDecoder); - Withdrawal[]? withdrawals = null; - ConsensusRequest[]? requests = null; - if (ctx.PeekNumberOfItemsRemaining(startingPosition + sequenceLength, 1) > 0) - { - withdrawals = ctx.DecodeArray(_withdrawalDecoderDecoder); - } - - if (ctx.PeekNumberOfItemsRemaining(startingPosition + sequenceLength, 1) > 0) - { - requests = ctx.DecodeArray(_requestsDecoder); - } - - return new BlockBody(transactions, uncles, withdrawals, requests); - } - - public void Serialize(RlpStream stream, BlockBody body) - { - stream.StartSequence(GetBodyLength(body)); - stream.StartSequence(GetTxLength(body.Transactions)); - foreach (Transaction? txn in body.Transactions) - { - stream.Encode(txn); - } - - stream.StartSequence(GetUnclesLength(body.Uncles)); - foreach (BlockHeader? uncle in body.Uncles) - { - stream.Encode(uncle); - } - - if (body.Withdrawals is not null) - { - stream.StartSequence(GetWithdrawalsLength(body.Withdrawals)); - foreach (Withdrawal? withdrawal in body.Withdrawals) - { - stream.Encode(withdrawal); - } - } - - if (body.Requests is not null) - { - stream.StartSequence(GetRequestsLength(body.Requests)); - foreach (ConsensusRequest? request in body.Requests) - { - stream.Encode(request); - } - } - } - } } } diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index 5f53d0f31eb..f7ce6c9b833 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -100,7 +100,7 @@ protected override BlockProcessor CreateBlockProcessor(BlockCachePreWarmer? preW api.ReceiptStorage, transactionProcessor, new BlockhashStore(api.SpecProvider, api.WorldState), - new BeaconBlockRootHandler(transactionProcessor), + new BeaconBlockRootHandler(transactionProcessor, api.WorldState), api.LogManager, api.SpecHelper, contractRewriter, diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs index 88ee38dd5e3..3056aa4fbad 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs @@ -89,7 +89,7 @@ protected override BlockProcessor CreateBlockProcessor( receiptStorage, readOnlyTxProcessingEnv.TransactionProcessor, new BlockhashStore(specProvider, readOnlyTxProcessingEnv.WorldState), - new BeaconBlockRootHandler(readOnlyTxProcessingEnv.TransactionProcessor), + new BeaconBlockRootHandler(readOnlyTxProcessingEnv.TransactionProcessor, readOnlyTxProcessingEnv.WorldState), logManager, _specHelper, new Create2DeployerContractRewriter(_specHelper, _specProvider, _blockTree), diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index 76633fbf876..33615392a99 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -158,7 +158,7 @@ public Task InitSynchronization() .AddSingleton(_beaconPivot) .AddSingleton(_api.PoSSwitcher) .AddSingleton(_mergeConfig) - .AddSingleton(_invalidChainTracker); + .AddSingleton(_invalidChainTracker); builder.RegisterModule(new SynchronizerModule(_syncConfig)); builder.RegisterModule(new MergeSynchronizerModule()); diff --git a/src/Nethermind/Nethermind.Optimism/ReadOnlyChainProcessingEnv.cs b/src/Nethermind/Nethermind.Optimism/ReadOnlyChainProcessingEnv.cs index 3e1e3cbe011..05e6b898ffe 100644 --- a/src/Nethermind/Nethermind.Optimism/ReadOnlyChainProcessingEnv.cs +++ b/src/Nethermind/Nethermind.Optimism/ReadOnlyChainProcessingEnv.cs @@ -65,7 +65,7 @@ IBlockProcessor.IBlockTransactionsExecutor transactionsExecutor receiptStorage, scope.TransactionProcessor, new BlockhashStore(specProvider, scope.WorldState), - new BeaconBlockRootHandler(scope.TransactionProcessor), + new BeaconBlockRootHandler(scope.TransactionProcessor, scope.WorldState), logManager, opSpecHelper, contractRewriter, diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs new file mode 100644 index 00000000000..6e38f63dc38 --- /dev/null +++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockBodyDecoder.cs @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Linq; +using System.Runtime.CompilerServices; +using Nethermind.Core; +using Nethermind.Core.ConsensusRequests; + +namespace Nethermind.Serialization.Rlp; + +public class BlockBodyDecoder : IRlpValueDecoder +{ + private readonly TxDecoder _txDecoder = TxDecoder.Instance; + private readonly HeaderDecoder _headerDecoder = new(); + private readonly WithdrawalDecoder _withdrawalDecoderDecoder = new(); + private readonly ConsensusRequestDecoder _requestsDecoder = ConsensusRequestDecoder.Instance; + + private static BlockBodyDecoder? _instance = null; + public static BlockBodyDecoder Instance => _instance ??= new BlockBodyDecoder(); + + // Cant set to private because of `Rlp.RegisterDecoder`. + public BlockBodyDecoder() + { + } + + public int GetLength(BlockBody item, RlpBehaviors rlpBehaviors) + { + return Rlp.LengthOfSequence(GetBodyLength(item)); + } + + public int GetBodyLength(BlockBody b) + { + (int txs, int uncles, int? withdrawals, int? requests) = GetBodyComponentLength(b); + return Rlp.LengthOfSequence(txs) + + Rlp.LengthOfSequence(uncles) + + (withdrawals is not null ? Rlp.LengthOfSequence(withdrawals.Value) : 0) + + (requests is not null ? Rlp.LengthOfSequence(requests.Value) : 0); + } + + public (int Txs, int Uncles, int? Withdrawals, int? Requests) GetBodyComponentLength(BlockBody b) => + ( + GetTxLength(b.Transactions), + GetUnclesLength(b.Uncles), + (b.Withdrawals is not null ? GetWithdrawalsLength(b.Withdrawals) : null), + (b.Requests is not null ? GetRequestsLength(b.Requests) : null) + ); + + private int GetTxLength(Transaction[] transactions) => transactions.Sum(t => _txDecoder.GetLength(t, RlpBehaviors.None)); + + private int GetUnclesLength(BlockHeader[] headers) => headers.Sum(t => _headerDecoder.GetLength(t, RlpBehaviors.None)); + + private int GetWithdrawalsLength(Withdrawal[] withdrawals) => withdrawals.Sum(t => _withdrawalDecoderDecoder.GetLength(t, RlpBehaviors.None)); + + private int GetRequestsLength(ConsensusRequest[] requests) => requests.Sum(t => _requestsDecoder.GetLength(t, RlpBehaviors.None)); + + public BlockBody? Decode(ref Rlp.ValueDecoderContext ctx, RlpBehaviors rlpBehaviors = RlpBehaviors.None) + { + int sequenceLength = ctx.ReadSequenceLength(); + int startingPosition = ctx.Position; + if (sequenceLength == 0) + { + return null; + } + + return DecodeUnwrapped(ref ctx, startingPosition + sequenceLength); + } + + public BlockBody? DecodeUnwrapped(ref Rlp.ValueDecoderContext ctx, int lastPosition) + { + + // quite significant allocations (>0.5%) here based on a sample 3M blocks sync + // (just on these delegates) + Transaction[] transactions = ctx.DecodeArray(_txDecoder); + BlockHeader[] uncles = ctx.DecodeArray(_headerDecoder); + Withdrawal[]? withdrawals = null; + ConsensusRequest[]? requests = null; + if (ctx.PeekNumberOfItemsRemaining(lastPosition, 1) > 0) + { + withdrawals = ctx.DecodeArray(_withdrawalDecoderDecoder); + } + + if (ctx.PeekNumberOfItemsRemaining(lastPosition, 1) > 0) + { + requests = ctx.DecodeArray(_requestsDecoder); + } + + return new BlockBody(transactions, uncles, withdrawals, requests); + } + + public void Serialize(RlpStream stream, BlockBody body) + { + stream.StartSequence(GetBodyLength(body)); + stream.StartSequence(GetTxLength(body.Transactions)); + foreach (Transaction? txn in body.Transactions) + { + stream.Encode(txn); + } + + stream.StartSequence(GetUnclesLength(body.Uncles)); + foreach (BlockHeader? uncle in body.Uncles) + { + stream.Encode(uncle); + } + + if (body.Withdrawals is not null) + { + stream.StartSequence(GetWithdrawalsLength(body.Withdrawals)); + foreach (Withdrawal? withdrawal in body.Withdrawals) + { + stream.Encode(withdrawal); + } + } + + if (body.Requests is not null) + { + stream.StartSequence(GetRequestsLength(body.Requests)); + foreach (ConsensusRequest? request in body.Requests) + { + stream.Encode(request); + } + } + } +} diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs index 0530f141fd8..89d1cfd7a83 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs @@ -12,9 +12,7 @@ namespace Nethermind.Serialization.Rlp public class BlockDecoder : IRlpValueDecoder, IRlpStreamDecoder { private readonly HeaderDecoder _headerDecoder = new(); - private readonly TxDecoder _txDecoder = TxDecoder.Instance; - private readonly WithdrawalDecoder _withdrawalDecoder = new(); - private readonly ConsensusRequestDecoder _consensusRequestsDecoder = ConsensusRequestDecoder.Instance; + private readonly BlockBodyDecoder _blockBodyDecoder = BlockBodyDecoder.Instance; public Block? Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { @@ -29,191 +27,27 @@ public class BlockDecoder : IRlpValueDecoder, IRlpStreamDecoder return null; } - int sequenceLength = rlpStream.ReadSequenceLength(); - int blockCheck = rlpStream.Position + sequenceLength; - - BlockHeader header = Rlp.Decode(rlpStream); - - int transactionsSequenceLength = rlpStream.ReadSequenceLength(); - int transactionsCheck = rlpStream.Position + transactionsSequenceLength; - List transactions = new(); - while (rlpStream.Position < transactionsCheck) - { - transactions.Add(Rlp.Decode(rlpStream, rlpBehaviors)); - } - - rlpStream.Check(transactionsCheck); - - int unclesSequenceLength = rlpStream.ReadSequenceLength(); - int unclesCheck = rlpStream.Position + unclesSequenceLength; - List uncleHeaders = new(); - while (rlpStream.Position < unclesCheck) - { - uncleHeaders.Add(Rlp.Decode(rlpStream, rlpBehaviors)); - } - - rlpStream.Check(unclesCheck); - - List? withdrawals = DecodeWithdrawals(rlpStream, blockCheck); - List? requests = DecodeRequests(rlpStream, blockCheck); - - if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) - { - rlpStream.Check(blockCheck); - } - - return new(header, transactions, uncleHeaders, withdrawals, requests); - } - - - private List? DecodeWithdrawals(RlpStream rlpStream, int blockCheck) - { - List? withdrawals = null; - if (rlpStream.Position != blockCheck) - { - bool lengthWasRead = true; - try - { - rlpStream.PeekNextRlpLength(); - } - catch - { - lengthWasRead = false; - } - - if (lengthWasRead) - { - int withdrawalsLength = rlpStream.ReadSequenceLength(); - int withdrawalsCheck = rlpStream.Position + withdrawalsLength; - withdrawals = new(); - - while (rlpStream.Position < withdrawalsCheck) - { - withdrawals.Add(Rlp.Decode(rlpStream)); - } - - rlpStream.Check(withdrawalsCheck); - } - } - - return withdrawals; + Span contentSpan = rlpStream.PeekNextItem(); + Rlp.ValueDecoderContext ctx = new Rlp.ValueDecoderContext(contentSpan); + Block? decoded = Decode(ref ctx, rlpBehaviors); + rlpStream.Position += contentSpan.Length; + return decoded; } - private List? DecodeRequests(RlpStream rlpStream, int blockCheck) - { - List? requests = null; - if (rlpStream.Position != blockCheck) - { - bool lengthWasRead = true; - try - { - rlpStream.PeekNextRlpLength(); - } - catch - { - lengthWasRead = false; - } - - if (lengthWasRead) - { - int requestsLength = rlpStream.ReadSequenceLength(); - int requestsCheck = rlpStream.Position + requestsLength; - requests = new(); - - while (rlpStream.Position < requestsCheck) - { - requests.Add(Rlp.Decode(rlpStream)); - } - - rlpStream.Check(requestsCheck); - } - } - - return requests; - } - - private (int Total, int Txs, int Uncles, int? Withdrawals, int? Requests) GetContentLength(Block item, RlpBehaviors rlpBehaviors) { - int contentLength = _headerDecoder.GetLength(item.Header, rlpBehaviors); - - int txLength = GetTxLength(item, rlpBehaviors); - contentLength += Rlp.LengthOfSequence(txLength); - - int unclesLength = GetUnclesLength(item, rlpBehaviors); - contentLength += Rlp.LengthOfSequence(unclesLength); - - int? withdrawalsLength = null; - if (item.Withdrawals is not null) - { - withdrawalsLength = GetWithdrawalsLength(item, rlpBehaviors); - - if (withdrawalsLength.HasValue) - contentLength += Rlp.LengthOfSequence(withdrawalsLength.Value); - } - - int? consensusRequestsLength = null; - if (item.Requests is not null) - { - consensusRequestsLength = GetConsensusRequestsLength(item, rlpBehaviors); - - if (consensusRequestsLength.HasValue) - contentLength += Rlp.LengthOfSequence(consensusRequestsLength.Value); - } - - return (contentLength, txLength, unclesLength, withdrawalsLength, consensusRequestsLength); - } - - private int GetUnclesLength(Block item, RlpBehaviors rlpBehaviors) - { - int unclesLength = 0; - for (int i = 0; i < item.Uncles.Length; i++) - { - unclesLength += _headerDecoder.GetLength(item.Uncles[i], rlpBehaviors); - } - - return unclesLength; - } - - private int GetTxLength(Block item, RlpBehaviors rlpBehaviors) - { - int txLength = 0; - for (int i = 0; i < item.Transactions.Length; i++) - { - txLength += _txDecoder.GetLength(item.Transactions[i], rlpBehaviors); - } - - return txLength; - } - - private int? GetWithdrawalsLength(Block item, RlpBehaviors rlpBehaviors) - { - if (item.Withdrawals is null) - return null; - - var withdrawalLength = 0; - - for (int i = 0, count = item.Withdrawals.Length; i < count; i++) - { - withdrawalLength += _withdrawalDecoder.GetLength(item.Withdrawals[i], rlpBehaviors); - } - - return withdrawalLength; - } - - private int? GetConsensusRequestsLength(Block item, RlpBehaviors rlpBehaviors) - { - if (item.Requests is null) - return null; + int headerLength = _headerDecoder.GetLength(item.Header, rlpBehaviors); - var consensusRequestsLength = 0; + (int txs, int uncles, int? withdrawals, int? requests) = _blockBodyDecoder.GetBodyComponentLength(item.Body); - for (int i = 0, count = item.Requests.Length; i < count; i++) - { - consensusRequestsLength += _consensusRequestsDecoder.GetLength(item.Requests[i], rlpBehaviors); - } + int contentLength = + headerLength + + Rlp.LengthOfSequence(txs) + + Rlp.LengthOfSequence(uncles) + + (withdrawals is not null ? Rlp.LengthOfSequence(withdrawals.Value) : 0) + + (requests is not null ? Rlp.LengthOfSequence(requests.Value) : 0); - return consensusRequestsLength; + return (contentLength, txs, uncles, withdrawals, requests); } public int GetLength(Block? item, RlpBehaviors rlpBehaviors) @@ -238,78 +72,8 @@ public int GetLength(Block? item, RlpBehaviors rlpBehaviors) int blockCheck = decoderContext.Position + sequenceLength; BlockHeader header = Rlp.Decode(ref decoderContext); - - int transactionsSequenceLength = decoderContext.ReadSequenceLength(); - int transactionsCheck = decoderContext.Position + transactionsSequenceLength; - List transactions = new(); - while (decoderContext.Position < transactionsCheck) - { - transactions.Add(Rlp.Decode(ref decoderContext, rlpBehaviors)); - } - - decoderContext.Check(transactionsCheck); - - int unclesSequenceLength = decoderContext.ReadSequenceLength(); - int unclesCheck = decoderContext.Position + unclesSequenceLength; - List uncleHeaders = new(); - while (decoderContext.Position < unclesCheck) - { - uncleHeaders.Add(Rlp.Decode(ref decoderContext, rlpBehaviors)); - } - - decoderContext.Check(unclesCheck); - - List? withdrawals = DecodeWithdrawals(ref decoderContext, blockCheck); - List? requests = DecodeRequests(ref decoderContext, blockCheck); - - if ((rlpBehaviors & RlpBehaviors.AllowExtraBytes) != RlpBehaviors.AllowExtraBytes) - { - decoderContext.Check(blockCheck); - } - - return new(header, transactions, uncleHeaders, withdrawals, requests); - } - - private List? DecodeWithdrawals(ref Rlp.ValueDecoderContext decoderContext, int blockCheck) - { - List? withdrawals = null; - - if (decoderContext.Position != blockCheck) - { - int withdrawalsLength = decoderContext.ReadSequenceLength(); - int withdrawalsCheck = decoderContext.Position + withdrawalsLength; - withdrawals = new(); - - while (decoderContext.Position < withdrawalsCheck) - { - withdrawals.Add(Rlp.Decode(ref decoderContext)); - } - - decoderContext.Check(withdrawalsCheck); - } - - return withdrawals; - } - - private List? DecodeRequests(ref Rlp.ValueDecoderContext decoderContext, int blockCheck) - { - List? requests = null; - - if (decoderContext.Position != blockCheck) - { - int requestsLength = decoderContext.ReadSequenceLength(); - int requestsCheck = decoderContext.Position + requestsLength; - requests = new(); - - while (decoderContext.Position < requestsCheck) - { - requests.Add(Rlp.Decode(ref decoderContext)); - } - - decoderContext.Check(requestsCheck); - } - - return requests; + BlockBody body = _blockBodyDecoder.DecodeUnwrapped(ref decoderContext, blockCheck); + return new(header, body); } public Rlp Encode(Block? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs index 33e43446a69..ada2c15efb3 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncThreadTests.cs @@ -307,7 +307,7 @@ private SyncTestContext CreateSyncManager(int index) stateProvider, receiptStorage, txProcessor, - new BeaconBlockRootHandler(txProcessor), + new BeaconBlockRootHandler(txProcessor, stateProvider), new BlockhashStore(specProvider, stateProvider), logManager); @@ -331,7 +331,7 @@ private SyncTestContext CreateSyncManager(int index) devState, receiptStorage, devTxProcessor, - new BeaconBlockRootHandler(devTxProcessor), + new BeaconBlockRootHandler(devTxProcessor, devState), new BlockhashStore(specProvider, devState), logManager); diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index b0cacf09bf0..b5c6bbcab66 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -673,6 +673,10 @@ public void WaitForPruning() private ConcurrentQueue CommitSetQueue => (_commitSetQueue ?? CreateQueueAtomic(ref _commitSetQueue)); +#if DEBUG + private BlockCommitSet? _lastCommitSet = null; +#endif + private long _memoryUsedByDirtyCache; private int _committedNodesCount; @@ -700,11 +704,18 @@ private BlockCommitSet CreateCommitSet(long blockNumber) if (_logger.IsDebug) _logger.Debug($"Beginning new {nameof(BlockCommitSet)} - {blockNumber}"); // TODO: this throws on reorgs, does it not? let us recreate it in test - Debug.Assert(!CommitSetQueue.TryPeek(out BlockCommitSet lastSet) || blockNumber == lastSet.BlockNumber + 1, $"Newly begun block is not a successor of the last one."); - Debug.Assert(!CommitSetQueue.TryPeek(out lastSet) || lastSet.IsSealed, "Not sealed when beginning new block"); +#if DEBUG + Debug.Assert(_lastCommitSet == null || blockNumber == _lastCommitSet.BlockNumber + 1 || _lastCommitSet.BlockNumber == 0, $"Newly begun block is not a successor of the last one."); + Debug.Assert(_lastCommitSet == null || _lastCommitSet.IsSealed, "Not sealed when beginning new block"); +#endif BlockCommitSet commitSet = new(blockNumber); CommitSetQueue.Enqueue(commitSet); + +#if DEBUG + _lastCommitSet = commitSet; +#endif + LatestCommittedBlockNumber = Math.Max(blockNumber, LatestCommittedBlockNumber); // Why are we announcing **before** committing next block?? // Should it be after commit?