diff --git a/src/Nethermind/Nethermind.Api/Extensions/INethermindPlugin.cs b/src/Nethermind/Nethermind.Api/Extensions/INethermindPlugin.cs index ad1c8c28027..2c9f2042f42 100644 --- a/src/Nethermind/Nethermind.Api/Extensions/INethermindPlugin.cs +++ b/src/Nethermind/Nethermind.Api/Extensions/INethermindPlugin.cs @@ -14,7 +14,7 @@ public interface INethermindPlugin : IAsyncDisposable string Author { get; } - void InitRlpDecoders(INethermindApi api) { } + void InitTxTypesAndRlpDecoders(INethermindApi api) { } Task Init(INethermindApi nethermindApi) => Task.CompletedTask; diff --git a/src/Nethermind/Nethermind.Crypto/TransactionExtensions.cs b/src/Nethermind/Nethermind.Crypto/TransactionExtensions.cs index 292b6959a31..9dd09eebc27 100644 --- a/src/Nethermind/Nethermind.Crypto/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.Crypto/TransactionExtensions.cs @@ -4,17 +4,17 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; -using System; namespace Nethermind.Crypto { public static class TransactionExtensions { - private static readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private static readonly TxDecoder _txDecoder = TxDecoder.Instance; + public static Hash256 CalculateHash(this Transaction transaction) { KeccakRlpStream stream = new(); - _txDecoder.Value.Encode(stream, transaction, RlpBehaviors.SkipTypedWrapping); + _txDecoder.Encode(stream, transaction, RlpBehaviors.SkipTypedWrapping); return stream.GetHash(); } } diff --git a/src/Nethermind/Nethermind.EthStats.Test/EthStatsPluginTests.cs b/src/Nethermind/Nethermind.EthStats.Test/EthStatsPluginTests.cs index 2deefaa5e7e..e0fffd67b31 100644 --- a/src/Nethermind/Nethermind.EthStats.Test/EthStatsPluginTests.cs +++ b/src/Nethermind/Nethermind.EthStats.Test/EthStatsPluginTests.cs @@ -32,7 +32,7 @@ public void Setup() public void Init_eth_stats_plugin_does_not_throw_exception(bool enabled) { StatsConfig = new EthStatsConfig() { Enabled = enabled }; - Assert.DoesNotThrow(() => _plugin.InitRlpDecoders(_context)); + Assert.DoesNotThrow(() => _plugin.InitTxTypesAndRlpDecoders(_context)); Assert.DoesNotThrowAsync(async () => await _plugin.Init(_context)); Assert.DoesNotThrowAsync(async () => await _plugin.InitNetworkProtocol()); Assert.DoesNotThrowAsync(async () => await _plugin.InitRpcModules()); diff --git a/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs b/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs index 8a562afdb72..b63b73770ca 100644 --- a/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs +++ b/src/Nethermind/Nethermind.Init/Steps/DatabaseMigrations.cs @@ -11,7 +11,7 @@ namespace Nethermind.Init.Steps { - [RunnerStepDependencies(typeof(InitRlp), typeof(InitDatabase), typeof(InitializeBlockchain), typeof(InitializeNetwork))] + [RunnerStepDependencies(typeof(InitTxTypesAndRlp), typeof(InitDatabase), typeof(InitializeBlockchain), typeof(InitializeNetwork))] public sealed class DatabaseMigrations : IStep { private readonly IApiWithNetwork _api; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitCrypto.cs b/src/Nethermind/Nethermind.Init/Steps/InitCrypto.cs index aa3a7f6a91c..51d51c4e18a 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitCrypto.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitCrypto.cs @@ -9,7 +9,7 @@ namespace Nethermind.Init.Steps { - [RunnerStepDependencies(typeof(InitRlp))] + [RunnerStepDependencies(typeof(InitTxTypesAndRlp))] public class InitCrypto : IStep { private readonly IBasicApi _api; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitRlp.cs b/src/Nethermind/Nethermind.Init/Steps/InitTxTypesAndRlp.cs similarity index 71% rename from src/Nethermind/Nethermind.Init/Steps/InitRlp.cs rename to src/Nethermind/Nethermind.Init/Steps/InitTxTypesAndRlp.cs index 9a8d7ec4051..f96f35c1fbb 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitRlp.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitTxTypesAndRlp.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Nethermind.Api; using Nethermind.Api.Extensions; +using Nethermind.Consensus.Validators; using Nethermind.Core.Attributes; using Nethermind.Network; using Nethermind.Serialization.Rlp; @@ -14,20 +15,18 @@ namespace Nethermind.Init.Steps { [RunnerStepDependencies(typeof(ApplyMemoryHint))] - public class InitRlp : IStep + public class InitTxTypesAndRlp(INethermindApi api) : IStep { - private readonly INethermindApi _api; - - public InitRlp(INethermindApi api) - { - _api = api ?? throw new ArgumentNullException(nameof(api)); - } + private readonly INethermindApi _api = api ?? throw new ArgumentNullException(nameof(api)); [Todo(Improve.Refactor, "Automatically scan all the references solutions?")] public virtual Task Execute(CancellationToken _) { if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); + // we need to initialize everything transaction related before block tree + _api.TxValidator = new TxValidator(_api.SpecProvider.ChainId); + Assembly? assembly = Assembly.GetAssembly(typeof(NetworkNodeDecoder)); if (assembly is not null) { @@ -36,7 +35,7 @@ public virtual Task Execute(CancellationToken _) foreach (INethermindPlugin plugin in _api.Plugins) { - plugin.InitRlpDecoders(_api); + plugin.InitTxTypesAndRlpDecoders(_api); } return Task.CompletedTask; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs index 021924c55dc..d0a6abb5c8e 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs @@ -20,7 +20,7 @@ namespace Nethermind.Init.Steps { - [RunnerStepDependencies(typeof(InitRlp), typeof(InitDatabase), typeof(MigrateConfigs), typeof(SetupKeyStore))] + [RunnerStepDependencies(typeof(InitTxTypesAndRlp), typeof(InitDatabase), typeof(MigrateConfigs), typeof(SetupKeyStore))] public class InitializeBlockTree : IStep { private readonly IBasicApi _get; diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 7583676cd3c..1c7d9f22a29 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -51,7 +51,6 @@ protected virtual Task InitBlockchain() { (IApiWithStores getApi, IApiWithBlockchain setApi) = _api.ForBlockchain; setApi.TransactionComparerProvider = new TransactionComparerProvider(getApi.SpecProvider!, getApi.BlockTree!.AsReadOnly()); - setApi.TxValidator = new TxValidator(_api.SpecProvider!.ChainId); IInitConfig initConfig = getApi.Config(); IBlocksConfig blocksConfig = getApi.Config(); @@ -93,7 +92,7 @@ protected virtual Task InitBlockchain() setApi.TxPoolInfoProvider = new TxPoolInfoProvider(chainHeadInfoProvider.AccountStateProvider, txPool); setApi.GasPriceOracle = new GasPriceOracle(getApi.BlockTree!, getApi.SpecProvider, _api.LogManager, blocksConfig.MinGasPrice); BlockCachePreWarmer? preWarmer = blocksConfig.PreWarmStateOnBlockProcessing - ? new(new(_api.WorldStateManager!, _api.BlockTree!, _api.SpecProvider, _api.LogManager, _api.WorldState), _api.SpecProvider, _api.LogManager, preBlockCaches) + ? new(new(_api.WorldStateManager!, _api.BlockTree!, _api.SpecProvider, _api.LogManager, _api.WorldState), _api.SpecProvider!, _api.LogManager, preBlockCaches) : null; IBlockProcessor mainBlockProcessor = setApi.MainBlockProcessor = CreateBlockProcessor(preWarmer); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index c61afeb1524..f7747d6436f 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -20,7 +20,6 @@ using Nethermind.JsonRpc.Data; using Nethermind.Logging; using Nethermind.Serialization.Rlp; -using Nethermind.Serialization.Rlp.TxDecoders; using Nethermind.State; using Nethermind.Trie; @@ -39,7 +38,7 @@ public class TraceRpcModule : ITraceRpcModule private readonly IReceiptFinder _receiptFinder; private readonly ITracer _tracer; private readonly IBlockFinder _blockFinder; - private readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private readonly TxDecoder _txDecoder = TxDecoder.Instance; private readonly IJsonRpcConfig _jsonRpcConfig; private readonly TimeSpan _cancellationTokenTimeout; private readonly IStateReader _stateReader; @@ -110,7 +109,7 @@ public ResultWrapper> trace_callMany(Transa /// public ResultWrapper trace_rawTransaction(byte[] data, string[] traceTypes) { - Transaction tx = _txDecoder.Value.Decode(new RlpStream(data), RlpBehaviors.SkipTypedWrapping); + Transaction tx = _txDecoder.Decode(new RlpStream(data), RlpBehaviors.SkipTypedWrapping); return TraceTx(tx, traceTypes, BlockParameter.Latest); } diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs index 61bfe27ec1d..b47db24a5ac 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/SyncPeerProtocolHandlerBase.cs @@ -52,7 +52,7 @@ public abstract class SyncPeerProtocolHandlerBase : ZeroProtocolHandlerBase, ISy protected Hash256 _remoteHeadBlockHash; protected readonly ITimestamper _timestamper; - protected readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + protected readonly TxDecoder _txDecoder; protected readonly MessageQueue> _headersRequests; protected readonly MessageQueue _bodiesRequests; @@ -87,6 +87,7 @@ protected SyncPeerProtocolHandlerBase(ISession session, SyncServer = syncServer ?? throw new ArgumentNullException(nameof(syncServer)); BackgroundTaskScheduler = new BackgroundTaskSchedulerWrapper(this, backgroundTaskScheduler ?? throw new ArgumentNullException(nameof(BackgroundTaskScheduler))); _timestamper = Timestamper.Default; + _txDecoder = TxDecoder.Instance; _headersRequests = new MessageQueue>(Send); _bodiesRequests = new MessageQueue(Send); 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 822f078e64f..65fd4af43d8 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 @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Linq; using DotNetty.Buffers; using Nethermind.Core; @@ -57,7 +56,7 @@ public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer) private class BlockBodyDecoder : IRlpValueDecoder { - private readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private readonly TxDecoder _txDecoder = TxDecoder.Instance; private readonly HeaderDecoder _headerDecoder = new(); private readonly WithdrawalDecoder _withdrawalDecoderDecoder = new(); private readonly ConsensusRequestDecoder _requestsDecoder = new(); @@ -73,7 +72,7 @@ public int GetBodyLength(BlockBody b) => + (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.Value.GetLength(t, RlpBehaviors.None)); + 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)); @@ -92,7 +91,7 @@ public int GetBodyLength(BlockBody b) => // quite significant allocations (>0.5%) here based on a sample 3M blocks sync // (just on these delegates) - Transaction[] transactions = ctx.DecodeArray(_txDecoder.Value); + Transaction[] transactions = ctx.DecodeArray(_txDecoder); BlockHeader[] uncles = ctx.DecodeArray(_headerDecoder); Withdrawal[]? withdrawals = null; ConsensusRequest[]? requests = null; @@ -115,7 +114,7 @@ public void Serialize(RlpStream stream, BlockBody body) stream.StartSequence(GetTxLength(body.Transactions)); foreach (Transaction? txn in body.Transactions) { - _txDecoder.Value.Encode(stream, txn); + stream.Encode(txn); } stream.StartSequence(GetUnclesLength(body.Uncles)); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs index d036a67b94c..94366d508f7 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs @@ -5,13 +5,12 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Serialization.Rlp; -using System; namespace Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages { public class TransactionsMessageSerializer : IZeroInnerMessageSerializer { - private readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private readonly TxDecoder _decoder = TxDecoder.Instance; public void Serialize(IByteBuffer byteBuffer, TransactionsMessage message) { @@ -22,7 +21,7 @@ public void Serialize(IByteBuffer byteBuffer, TransactionsMessage message) nettyRlpStream.StartSequence(contentLength); for (int i = 0; i < message.Transactions.Count; i++) { - _txDecoder.Value.Encode(nettyRlpStream, message.Transactions[i], RlpBehaviors.InMempoolForm); + nettyRlpStream.Encode(message.Transactions[i], RlpBehaviors.InMempoolForm); } } @@ -38,7 +37,7 @@ public int GetLength(TransactionsMessage message, out int contentLength) contentLength = 0; for (int i = 0; i < message.Transactions.Count; i++) { - contentLength += _txDecoder.Value.GetLength(message.Transactions[i], RlpBehaviors.InMempoolForm); + contentLength += _decoder.GetLength(message.Transactions[i], RlpBehaviors.InMempoolForm); } return Rlp.LengthOfSequence(contentLength); diff --git a/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs b/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs new file mode 100644 index 00000000000..ffd084d7eb3 --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Test.Builders; +using Nethermind.Serialization.Rlp; +using NUnit.Framework; + +namespace Nethermind.Optimism.Test; + +public class RlpDecoderTests +{ + [Test] + public void Can_decode_non_null_Transaction() + { + TxDecoder decoder = TxDecoder.Instance; + decoder.RegisterDecoder(new OptimismTxDecoder()); + + Transaction tx = Build.A.Transaction.WithType(TxType.DepositTx).TestObject; + + RlpStream rlpStream = new(decoder.GetLength(tx, RlpBehaviors.None)); + decoder.Encode(rlpStream, tx); + rlpStream.Reset(); + + Transaction? decodedTx = decoder.Decode(rlpStream); + + decodedTx.Should().NotBeNull(); + } + + [Test] + public void Can_decode_non_null_Transaction_through_Rlp() + { + TxDecoder decoder = TxDecoder.Instance; + decoder.RegisterDecoder(new OptimismTxDecoder()); + + Transaction tx = Build.A.Transaction.WithType(TxType.DepositTx).TestObject; + + RlpStream rlpStream = new(decoder.GetLength(tx, RlpBehaviors.None)); + decoder.Encode(rlpStream, tx); + rlpStream.Reset(); + + Transaction? decodedTx = Rlp.Decode(rlpStream); + + decodedTx.Should().NotBeNull(); + } +} diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index 273bd424db2..32eaa382de9 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -11,7 +11,6 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Validators; using Nethermind.Consensus.Withdrawals; -using Nethermind.Core; using Nethermind.Evm; using Nethermind.Evm.TransactionProcessing; using Nethermind.Init.Steps; @@ -29,8 +28,6 @@ protected override async Task InitBlockchain() api.L1CostHelper = new(api.SpecHelper, api.ChainSpec.Optimism.L1BlockAddress); await base.InitBlockchain(); - - api.RegisterTxType(TxType.DepositTx, new OptimismTxDecoder(), Always.Valid); } protected override ITransactionProcessor CreateTransactionProcessor(CodeInfoRepository codeInfoRepository, VirtualMachine virtualMachine) diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index 3be0a603d12..82d7d0665c4 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -20,6 +20,8 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus.Rewards; +using Nethermind.Consensus.Validators; +using Nethermind.Core; using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Synchronization.ParallelSync; using Nethermind.HealthChecks; @@ -74,10 +76,11 @@ public INethermindApi CreateApi(IConfigProvider configProvider, IJsonSerializer ILogManager logManager, ChainSpec chainSpec) => new OptimismNethermindApi(configProvider, jsonSerializer, logManager, chainSpec); - public void InitRlpDecoders(INethermindApi api) + public void InitTxTypesAndRlpDecoders(INethermindApi api) { if (ShouldRunSteps(api)) { + api.RegisterTxType(TxType.DepositTx, new OptimismTxDecoder(), Always.Valid); Rlp.RegisterDecoders(typeof(OptimismReceiptMessageDecoder).Assembly, true); } } diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs index ea56d6fcabd..3c6eba08339 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockDecoder.cs @@ -12,7 +12,7 @@ namespace Nethermind.Serialization.Rlp public class BlockDecoder : IRlpValueDecoder, IRlpStreamDecoder { private readonly HeaderDecoder _headerDecoder = new(); - private readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private readonly TxDecoder _txDecoder = TxDecoder.Instance; private readonly WithdrawalDecoder _withdrawalDecoder = new(); private readonly ConsensusRequestDecoder _consensusRequestsDecoder = new(); @@ -180,7 +180,7 @@ private int GetTxLength(Block item, RlpBehaviors rlpBehaviors) int txLength = 0; for (int i = 0; i < item.Transactions.Length; i++) { - txLength += _txDecoder.Value.GetLength(item.Transactions[i], rlpBehaviors); + txLength += _txDecoder.GetLength(item.Transactions[i], rlpBehaviors); } return txLength; @@ -338,7 +338,7 @@ public void Encode(RlpStream stream, Block? item, RlpBehaviors rlpBehaviors = Rl stream.StartSequence(txsLength); for (int i = 0; i < item.Transactions.Length; i++) { - _txDecoder.Value.Encode(stream, item.Transactions[i]); + stream.Encode(item.Transactions[i]); } stream.StartSequence(unclesLength); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs index ffa6eada5a9..6672a485297 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs @@ -25,6 +25,7 @@ public class RlpStream private static readonly HeaderDecoder _headerDecoder = new(); private static readonly BlockDecoder _blockDecoder = new(); private static readonly BlockInfoDecoder _blockInfoDecoder = new(); + private static readonly TxDecoder _txDecoder = TxDecoder.Instance; private static readonly WithdrawalDecoder _withdrawalDecoder = new(); private static readonly ConsensusRequestDecoder _requestsDecoder = new(); private static readonly LogEntryDecoder _logEntryDecoder = LogEntryDecoder.Instance; @@ -65,6 +66,11 @@ public void Encode(BlockHeader value) _headerDecoder.Encode(this, value); } + public void Encode(Transaction value, RlpBehaviors rlpBehaviors = RlpBehaviors.None) + { + _txDecoder.Encode(this, value, rlpBehaviors); + } + public void Encode(Withdrawal value) => _withdrawalDecoder.Encode(this, value); public void Encode(ConsensusRequest value) => _requestsDecoder.Encode(this, value); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs index df1dbb0da38..6a720d6e5e5 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/TxDecoder.cs @@ -9,18 +9,21 @@ namespace Nethermind.Serialization.Rlp; +[Rlp.SkipGlobalRegistration] public sealed class TxDecoder : TxDecoder { - public static readonly ObjectPool TxObjectPool = new DefaultObjectPool(new Transaction.PoolPolicy(), Environment.ProcessorCount * 4); + public static readonly ObjectPool TxObjectPool; -#pragma warning disable CS0618 - public static TxDecoder Instance => Rlp.GetStreamDecoder() as TxDecoder; -#pragma warning restore CS0618 + public static readonly TxDecoder Instance; - // Rlp will try to find a public parameterless constructor during static initialization. - // The lambda cannot be removed due to static block initialization order. - [Obsolete("Use `TxDecoder.Instance` instead")] - public TxDecoder() : base(() => TxObjectPool.Get()) { } + private TxDecoder(Func transactionFactory) : base(transactionFactory) { } + + static TxDecoder() + { + TxObjectPool = new DefaultObjectPool(new Transaction.PoolPolicy(), Environment.ProcessorCount * 4); + Instance = new TxDecoder(() => TxObjectPool.Get()); + Rlp.RegisterDecoder(typeof(Transaction), Instance); + } } public sealed class SystemTxDecoder : TxDecoder; diff --git a/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs b/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs index 6f23e3ed1c2..d0858baf54c 100644 --- a/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs +++ b/src/Nethermind/Nethermind.State/Proofs/TxTrie.cs @@ -16,7 +16,7 @@ namespace Nethermind.State.Proofs; /// public class TxTrie : PatriciaTrie { - private static readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private static readonly TxDecoder _txDecoder = TxDecoder.Instance; /// /// The transactions to build the trie of. @@ -29,7 +29,7 @@ protected override void Initialize(Transaction[] list) foreach (Transaction? transaction in list) { - CappedArray buffer = _txDecoder.Value.EncodeToCappedArray(transaction, RlpBehaviors.SkipTypedWrapping, _bufferPool); + CappedArray buffer = _txDecoder.EncodeToCappedArray(transaction, RlpBehaviors.SkipTypedWrapping, _bufferPool); CappedArray keyBuffer = (key++).EncodeToCappedArray(_bufferPool); Set(keyBuffer.AsSpan(), buffer); diff --git a/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs b/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs index f6303e9ebd1..796890a25f1 100644 --- a/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs +++ b/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs @@ -17,7 +17,7 @@ namespace Nethermind.TxPool; public class BlobTxStorage : IBlobTxStorage { - private static readonly Lazy _txDecoder = new(() => TxDecoder.Instance); + private static readonly TxDecoder _txDecoder = TxDecoder.Instance; private readonly IDb _fullBlobTxsDb; private readonly IDb _lightBlobTxsDb; private readonly IDb _processedBlobTxsDb; @@ -96,7 +96,7 @@ public bool TryGetBlobTransactionsFromBlock(long blockNumber, out Transaction[]? if (bytes is not null) { RlpStream rlpStream = new(bytes); - blockBlobTransactions = _txDecoder.Value.DecodeArray(rlpStream, RlpBehaviors.InMempoolForm); + blockBlobTransactions = _txDecoder.DecodeArray(rlpStream, RlpBehaviors.InMempoolForm); return true; } @@ -141,10 +141,10 @@ private static void GetHashPrefixedByTimestamp(UInt256 timestamp, ValueHash256 h private void EncodeAndSaveTx(Transaction transaction, IDb db, Span txHashPrefixed) { - int length = _txDecoder.Value.GetLength(transaction, RlpBehaviors.InMempoolForm); + int length = _txDecoder.GetLength(transaction, RlpBehaviors.InMempoolForm); IByteBuffer byteBuffer = PooledByteBufferAllocator.Default.Buffer(length); using NettyRlpStream rlpStream = new(byteBuffer); - _txDecoder.Value.Encode(rlpStream, transaction, RlpBehaviors.InMempoolForm); + rlpStream.Encode(transaction, RlpBehaviors.InMempoolForm); db.PutSpan(txHashPrefixed, byteBuffer.AsSpan()); } @@ -158,7 +158,7 @@ private void EncodeAndSaveTxs(IList blockBlobTransactions, IDb db, rlpStream.StartSequence(contentLength); foreach (Transaction transaction in blockBlobTransactions) { - _txDecoder.Value.Encode(rlpStream, transaction, RlpBehaviors.InMempoolForm); + _txDecoder.Encode(rlpStream, transaction, RlpBehaviors.InMempoolForm); } db.PutSpan(blockNumber.ToBigEndianSpanWithoutLeadingZeros(out _), byteBuffer.AsSpan()); @@ -169,7 +169,7 @@ private int GetLength(IList blockBlobTransactions) int contentLength = 0; foreach (Transaction transaction in blockBlobTransactions) { - contentLength += _txDecoder.Value.GetLength(transaction, RlpBehaviors.InMempoolForm); + contentLength += _txDecoder.GetLength(transaction, RlpBehaviors.InMempoolForm); } return contentLength; diff --git a/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs b/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs index 87c11cef3b8..44598b63e01 100644 --- a/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs +++ b/src/Nethermind/Nethermind.TxPool/TransactionExtensions.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Runtime.CompilerServices; using Nethermind.Core; using Nethermind.Core.Extensions; @@ -15,11 +14,11 @@ namespace Nethermind.TxPool public static class TransactionExtensions { private static readonly long MaxSizeOfTxForBroadcast = 4.KiB(); //4KB, as in Geth https://github.com/ethereum/go-ethereum/pull/27618 - private static readonly Lazy _transactionSizeCalculator = new(() => new NetworkTransactionSizeCalculator(TxDecoder.Instance)); + private static readonly ITransactionSizeCalculator _transactionSizeCalculator = new NetworkTransactionSizeCalculator(TxDecoder.Instance); public static int GetLength(this Transaction tx) { - return tx.GetLength(_transactionSizeCalculator.Value); + return tx.GetLength(_transactionSizeCalculator); } public static bool CanPayBaseFee(this Transaction tx, UInt256 currentBaseFee) => tx.MaxFeePerGas >= currentBaseFee;