From ecd8a2a310a405bb19b234eb228cee3021142749 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Thu, 25 Jan 2024 11:31:46 +0100 Subject: [PATCH] Fix TraceStore plugin (#6609) Co-authored-by: Ben Adams --- .../Tracing/ParityStyle/ParityAction.cs | 3 - .../ParityStyle/ParityTraceActionConverter.cs | 2 + .../Data/SerializationTestBase.cs | 24 +--- .../ParityTraceActionSerializationTests.cs | 22 +-- .../DbPersistingBlockTracerTests.cs | 128 ++++++++++++++++-- .../ITraceStoreConfig.cs | 2 +- .../ParityLikeTraceSerializer.cs | 9 +- .../TraceStoreConfig.cs | 4 +- .../Modules/Trace/ParityTxTraceFromReplay.cs | 2 +- .../Modules/Trace/ParityTxTraceFromStore.cs | 1 + .../Modules/Trace/TraceRpcModule.cs | 4 +- .../EthereumJsonSerializer.cs | 42 +++--- .../ForcedNumberConversion.cs | 2 +- 13 files changed, 173 insertions(+), 72 deletions(-) diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAction.cs b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAction.cs index d268fa394c7..57e681007c5 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAction.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityAction.cs @@ -9,12 +9,10 @@ namespace Nethermind.Evm.Tracing.ParityStyle { - [JsonConverter(typeof(ParityTraceActionConverter))] public class ParityTraceAction { public int[]? TraceAddress { get; set; } public string? CallType { get; set; } - public bool IncludeInTrace { get; set; } = true; public bool IsPrecompiled { get; set; } public string? Type { get; set; } @@ -26,7 +24,6 @@ public class ParityTraceAction public byte[]? Input { get; set; } public ParityTraceResult? Result { get; set; } = new(); public List Subtraces { get; set; } = new(); - public Address? Author { get; set; } public string? RewardType { get; set; } public string? Error { get; set; } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityTraceActionConverter.cs b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityTraceActionConverter.cs index 12e9338c0c0..d653f532281 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityTraceActionConverter.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/ParityStyle/ParityTraceActionConverter.cs @@ -23,6 +23,8 @@ namespace Nethermind.Evm.Tracing.ParityStyle */ public class ParityTraceActionConverter : JsonConverter { + public static readonly ParityTraceActionConverter Instance = new(); + public override ParityTraceAction Read( ref Utf8JsonReader reader, Type typeToConvert, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/SerializationTestBase.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/SerializationTestBase.cs index b59b99ffe04..db650894885 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/SerializationTestBase.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/SerializationTestBase.cs @@ -2,11 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Text.Json.Serialization; - -using Nethermind.JsonRpc.Data; -using Nethermind.JsonRpc.Modules.Eth; -using Nethermind.JsonRpc.Modules.Trace; using Nethermind.Serialization.Json; using NUnit.Framework; @@ -47,32 +44,23 @@ protected void TestRoundtrip(T item, Func? equalityComparer, stri TestRoundtrip(item, equalityComparer, null, description); } - protected void TestRoundtrip(string json, JsonConverter? converter = null) + protected void TestRoundtrip(string json, params JsonConverter[] converters) { - IJsonSerializer serializer = BuildSerializer(); + IJsonSerializer serializer = BuildSerializer(converters); T deserialized = serializer.Deserialize(json); string result = serializer.Serialize(deserialized); Assert.That(result, Is.EqualTo(json)); } - private void TestToJson(T item, JsonConverter? converter, string expectedResult) + protected void TestToJson(T item, string expectedResult, params JsonConverter[] converters) { - IJsonSerializer serializer = BuildSerializer(); + IJsonSerializer serializer = BuildSerializer(converters); string result = serializer.Serialize(item); Assert.That(result, Is.EqualTo(expectedResult.Replace("+", "\\u002B")), result.Replace("\"", "\\\"")); } - protected void TestToJson(T item, string expectedResult) - { - TestToJson(item, null, expectedResult); - } - - private static IJsonSerializer BuildSerializer() - { - IJsonSerializer serializer = new EthereumJsonSerializer(); - return serializer; - } + private static IJsonSerializer BuildSerializer(params JsonConverter[] converters) => new EthereumJsonSerializer(converters); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityTraceActionSerializationTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityTraceActionSerializationTests.cs index 66700eb76e7..d5e71eac5bc 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityTraceActionSerializationTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityTraceActionSerializationTests.cs @@ -15,16 +15,18 @@ public class ParityTraceActionSerializationTests : SerializationTestBase [Test] public void Can_serialize() { - ParityTraceAction action = new(); - action.From = TestItem.AddressA; - action.Gas = 12345; - action.Input = new byte[] { 6, 7, 8, 9, 0 }; - action.To = TestItem.AddressB; - action.Value = 24680; - action.CallType = "call"; - action.TraceAddress = new int[] { 1, 3, 5, 7 }; + ParityTraceAction action = new() + { + From = TestItem.AddressA, + Gas = 12345, + Input = [6, 7, 8, 9, 0], + To = TestItem.AddressB, + Value = 24680, + CallType = "call", + TraceAddress = [1, 3, 5, 7] + }; - TestToJson(action, "{\"callType\":\"call\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"gas\":\"0x3039\",\"input\":\"0x0607080900\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x6068\"}"); + TestToJson(action, "{\"callType\":\"call\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"gas\":\"0x3039\",\"input\":\"0x0607080900\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x6068\"}", ParityTraceActionConverter.Instance); } [Test] @@ -32,7 +34,7 @@ public void Can_serialize_nulls() { ParityTraceAction action = new(); - TestToJson(action, "{\"callType\":null,\"from\":null,\"gas\":\"0x0\",\"input\":null,\"to\":null,\"value\":\"0x0\"}"); + TestToJson(action, "{\"callType\":null,\"from\":null,\"gas\":\"0x0\",\"input\":null,\"to\":null,\"value\":\"0x0\"}", ParityTraceActionConverter.Instance); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs index 808ca83af13..d9b729aa624 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore.Test/DbPersistingBlockTracerTests.cs @@ -1,11 +1,16 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Collections.Generic; +using System.Linq; using FluentAssertions; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Evm; +using Nethermind.Evm.Tracing; using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Logging; using NUnit.Framework; @@ -15,24 +20,117 @@ namespace Nethermind.JsonRpc.TraceStore.Tests; [Parallelizable(ParallelScope.All)] public class DbPersistingBlockTracerTests { + private class Test + { + public DbPersistingBlockTracer DbPersistingTracer { get; } + public ParityLikeTraceSerializer Serializer { get; } + public MemDb Db { get; } + + public Test() + { + ParityLikeBlockTracer parityTracer = new(ParityTraceTypes.Trace); + Db = new(); + Serializer = new(LimboLogs.Instance); + DbPersistingTracer = new(parityTracer, Db, Serializer, LimboLogs.Instance); + } + + public (Hash256 hash, List traces) Trace(Action? customTrace = null) + { + Transaction transaction = Build.A.Transaction.TestObject; + Block block = Build.A.Block.WithTransactions(transaction).TestObject; + DbPersistingTracer.StartNewBlockTrace(block); + ITxTracer txTracer = DbPersistingTracer.StartNewTxTrace(transaction); + customTrace?.Invoke(txTracer); + DbPersistingTracer.EndTxTrace(); + DbPersistingTracer.EndBlockTrace(); + Hash256 hash = block.Hash!; + return (hash, Serializer.Deserialize(Db.Get(hash))!); + } + } + [Test] public void saves_traces_to_db() { - ParityLikeBlockTracer parityTracer = new(ParityTraceTypes.Trace); - MemDb memDb = new(); - ParityLikeTraceSerializer serializer = new(LimboLogs.Instance); - DbPersistingBlockTracer dbPersistingTracer = - new(parityTracer, memDb, serializer, LimboLogs.Instance); - - Transaction transaction = Build.A.Transaction.TestObject; - Block block = Build.A.Block.WithTransactions(transaction).TestObject; - dbPersistingTracer.StartNewBlockTrace(block); - dbPersistingTracer.StartNewTxTrace(transaction); - dbPersistingTracer.EndTxTrace(); - dbPersistingTracer.EndBlockTrace(); - - List? traces = serializer.Deserialize(memDb.Get(block.Hash!)); - traces.Should().BeEquivalentTo(new ParityLikeTxTrace[] { new() { BlockHash = block.Hash, TransactionPosition = 0 } }); + Test test = new(); + (Hash256 hash, List traces) = test.Trace(tracer => + { + tracer.ReportAction(100, 50, TestItem.AddressA, TestItem.AddressB, TestItem.RandomDataA, ExecutionType.CALL); + tracer.ReportAction(80, 20, TestItem.AddressB, TestItem.AddressC, TestItem.RandomDataC, ExecutionType.CREATE); + tracer.ReportActionEnd(60, TestItem.RandomDataD); + tracer.ReportActionEnd(50, TestItem.RandomDataB); + } + ); + + traces.Should().BeEquivalentTo(new ParityLikeTxTrace[] + { + new() + { + BlockHash = hash, + TransactionPosition = 0, + Action = new ParityTraceAction + { + CallType = "call", + From = TestItem.AddressA, + Gas = 100, + IncludeInTrace = true, + Input = TestItem.RandomDataA, + Result = new ParityTraceResult { GasUsed = 50, Output = TestItem.RandomDataB }, + To = TestItem.AddressB, + TraceAddress = Array.Empty(), + Type = "call", + Value = 50, + Subtraces = + [ + new() + { + CallType = "create", + From = TestItem.AddressB, + Gas = 80, + IncludeInTrace = true, + Input = TestItem.RandomDataC, + Result = new ParityTraceResult { GasUsed = 20, Output = TestItem.RandomDataD }, + Subtraces = new List(), + To = TestItem.AddressC, + TraceAddress = [0], + CreationMethod = "create", + Type = "create", + Value = 20 + } + ] + } + } + }); + } + + [TestCase(510)] + [TestCase(1020)] + [TestCase(1500)] + public void check_depth(int depth) + { + // depth = depth / 2 - 1; + Test test = new(); + (_, List traces) = test.Trace(tracer => + { + for (int i = 0; i < depth; i++) + { + tracer.ReportAction(100, 50, TestItem.AddressA, TestItem.AddressB, TestItem.RandomDataA, ExecutionType.CALL); + } + + for (int i = 0; i < depth; i++) + { + tracer.ReportActionEnd(60, TestItem.RandomDataD); + } + } + ); + + ParityTraceAction? action = traces.FirstOrDefault()?.Action; + int checkedDepth = 0; + while (action is not null) + { + checkedDepth += 1; + action = action.Subtraces.FirstOrDefault(); + } + checkedDepth.Should().Be(depth); } } diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceStoreConfig.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceStoreConfig.cs index 3f1c4dc6392..b4ba1745f6d 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceStoreConfig.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ITraceStoreConfig.cs @@ -20,7 +20,7 @@ public interface ITraceStoreConfig : IConfig [ConfigItem(Description = "Whether to verify all serialized elements.", DefaultValue = "false", HiddenFromDocs = true)] bool VerifySerialized { get; set; } - [ConfigItem(Description = "The max depth allowed when deserializing traces.", DefaultValue = "1024", HiddenFromDocs = true)] + [ConfigItem(Description = "The max depth allowed when deserializing traces.", DefaultValue = "3200", HiddenFromDocs = true)] int MaxDepth { get; set; } [ConfigItem(Description = "The max parallelization when deserialization requests the `trace_filter` method. `0` to use the number of logical processors. If you experience a resource shortage, set to a low number.", DefaultValue = "0")] diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs index ee7d4c5e0da..563e1960138 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/ParityLikeTraceSerializer.cs @@ -12,6 +12,7 @@ namespace Nethermind.JsonRpc.TraceStore; public class ParityLikeTraceSerializer : ITraceSerializer { + public const int DefaultDepth = 3200; private static readonly byte[] _emptyBytes = { 0 }; private static readonly List _emptyTraces = new(); @@ -20,7 +21,7 @@ public class ParityLikeTraceSerializer : ITraceSerializer private readonly int _maxDepth; private readonly bool _verifySerialized; - public ParityLikeTraceSerializer(ILogManager logManager, int maxDepth = 1024, bool verifySerialized = false) + public ParityLikeTraceSerializer(ILogManager logManager, int maxDepth = DefaultDepth, bool verifySerialized = false) { _jsonSerializer = new EthereumJsonSerializer(maxDepth); _maxDepth = maxDepth; @@ -30,7 +31,7 @@ public ParityLikeTraceSerializer(ILogManager logManager, int maxDepth = 1024, bo public unsafe List? Deserialize(Span serialized) { - if (serialized.Length == 1) return _emptyTraces; + if (serialized.Length <= 1) return _emptyTraces; fixed (byte* pBuffer = &serialized[0]) { @@ -102,9 +103,9 @@ private void CheckDepth(ParityTraceAction action, int depth) throw new ArgumentException("Trace depth is too high"); } - foreach (ParityTraceAction subAction in action.Subtraces) + for (var index = 0; index < action.Subtraces.Count; index++) { - CheckDepth(subAction, depth); + CheckDepth(action.Subtraces[index], depth); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreConfig.cs b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreConfig.cs index 59d86ef9e56..c7a7f62533c 100644 --- a/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreConfig.cs +++ b/src/Nethermind/Nethermind.JsonRpc.TraceStore/TraceStoreConfig.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Evm.Tracing.ParityStyle; +using Nethermind.Serialization.Json; +using Newtonsoft.Json; namespace Nethermind.JsonRpc.TraceStore; @@ -11,6 +13,6 @@ public class TraceStoreConfig : ITraceStoreConfig public int BlocksToKeep { get; set; } = 10000; public ParityTraceTypes TraceTypes { get; set; } = ParityTraceTypes.Trace | ParityTraceTypes.Rewards; public bool VerifySerialized { get; set; } = false; - public int MaxDepth { get; set; } = 1024; + public int MaxDepth { get; set; } = ParityLikeTraceSerializer.DefaultDepth; public int DeserializationParallelization { get; set; } = 0; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromReplay.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromReplay.cs index fc10b908d10..a37074ddded 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromReplay.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromReplay.cs @@ -73,7 +73,7 @@ public override void Write( writer.WriteStartObject(); writer.WritePropertyName("action"u8); - JsonSerializer.Serialize(writer, value, options); + ParityTraceActionConverter.Instance.Write(writer, value, options); if (value.Error is null) { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromStore.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromStore.cs index febabd3337d..91c814cfb69 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromStore.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/ParityTxTraceFromStore.cs @@ -62,6 +62,7 @@ private ParityTxTraceFromStore() { } + [JsonConverter(typeof(ParityTraceActionConverter))] public ParityTraceAction Action { get; set; } public Hash256 BlockHash { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs index 9417709fc67..903fb1b1bfc 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Trace/TraceRpcModule.cs @@ -238,7 +238,7 @@ public ResultWrapper> trace_filter(TraceFilt return GetStateFailureResult>(block.Header); } - IReadOnlyCollection txTracesFromOneBlock = ExecuteBlock(block!, new((ParityTraceTypes)(ParityTraceTypes.Trace | ParityTraceTypes.Rewards))); + IReadOnlyCollection txTracesFromOneBlock = ExecuteBlock(block!, new(ParityTraceTypes.Trace | ParityTraceTypes.Rewards)); txTraces.AddRange(txTracesFromOneBlock); } @@ -263,7 +263,7 @@ public ResultWrapper> trace_block(BlockParam return GetStateFailureResult>(block.Header); } - IReadOnlyCollection txTraces = ExecuteBlock(block, new((ParityTraceTypes)(ParityTraceTypes.Trace | ParityTraceTypes.Rewards))); + IReadOnlyCollection txTraces = ExecuteBlock(block, new(ParityTraceTypes.Trace | ParityTraceTypes.Rewards)); return ResultWrapper>.Success(txTraces.SelectMany(ParityTxTraceFromStore.FromTxTrace)); } diff --git a/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs b/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs index c4af68f59c5..1a2ec8d069f 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/EthereumJsonSerializer.cs @@ -6,27 +6,32 @@ using System.Collections.Generic; using System.IO; using System.IO.Pipelines; +using System.Linq; +using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization; -using System.Threading; using System.Threading.Tasks; +using Nethermind.Core.Collections; namespace Nethermind.Serialization.Json { public class EthereumJsonSerializer : IJsonSerializer { + private readonly int? _maxDepth; private readonly JsonSerializerOptions _jsonOptions; + public EthereumJsonSerializer(IEnumerable converters, int? maxDepth = null) + { + _maxDepth = maxDepth; + _jsonOptions = maxDepth.HasValue + ? CreateOptions(indented: false, maxDepth: maxDepth.Value, converters: converters) + : CreateOptions(indented: false, converters: converters); + } + public EthereumJsonSerializer(int? maxDepth = null) { - if (maxDepth.HasValue) - { - _jsonOptions = CreateOptions(indented: false, maxDepth.Value); - } - else - { - _jsonOptions = JsonOptions; - } + _maxDepth = maxDepth; + _jsonOptions = maxDepth.HasValue ? CreateOptions(indented: false, maxDepth: maxDepth.Value) : JsonOptions; } public T Deserialize(Stream stream) @@ -49,7 +54,7 @@ public string Serialize(T value, bool indented = false) return JsonSerializer.Serialize(value, indented ? JsonOptionsIndented : _jsonOptions); } - private static JsonSerializerOptions CreateOptions(bool indented, int maxDepth = 64) + private static JsonSerializerOptions CreateOptions(bool indented, IEnumerable converters = null, int maxDepth = 64) { var options = new JsonSerializerOptions { @@ -83,10 +88,8 @@ private static JsonSerializerOptions CreateOptions(bool indented, int maxDepth = } }; - foreach (var converter in _additionalConverters) - { - options.Converters.Add(converter); - } + options.Converters.AddRange(_additionalConverters); + options.Converters.AddRange(converters ?? Array.Empty()); return options; } @@ -115,7 +118,7 @@ private static CountingStreamPipeWriter GetPipeWriter(Stream stream, bool leaveO public long Serialize(Stream stream, T value, bool indented = false, bool leaveOpen = true) { var countingWriter = GetPipeWriter(stream, leaveOpen); - using var writer = new Utf8JsonWriter(countingWriter, new JsonWriterOptions() { SkipValidation = true, Indented = indented }); + using var writer = new Utf8JsonWriter(countingWriter, CreateWriterOptions(indented)); JsonSerializer.Serialize(writer, value, indented ? JsonOptionsIndented : _jsonOptions); countingWriter.Complete(); @@ -123,6 +126,13 @@ public long Serialize(Stream stream, T value, bool indented = false, bool lea return outputCount; } + private JsonWriterOptions CreateWriterOptions(bool indented) + { + JsonWriterOptions writerOptions = new JsonWriterOptions { SkipValidation = true, Indented = indented }; + writerOptions.MaxDepth = _maxDepth ?? writerOptions.MaxDepth; + return writerOptions; + } + public async ValueTask SerializeAsync(Stream stream, T value, bool indented = false, bool leaveOpen = true) { var writer = GetPipeWriter(stream, leaveOpen); @@ -135,7 +145,7 @@ public async ValueTask SerializeAsync(Stream stream, T value, bool inde public void Serialize(IBufferWriter writer, T value, bool indented = false) { - using var jsonWriter = new Utf8JsonWriter(writer, new JsonWriterOptions() { SkipValidation = true, Indented = indented }); + using var jsonWriter = new Utf8JsonWriter(writer, CreateWriterOptions(indented)); JsonSerializer.Serialize(jsonWriter, value, indented ? JsonOptionsIndented : _jsonOptions); } diff --git a/src/Nethermind/Nethermind.Serialization.Json/ForcedNumberConversion.cs b/src/Nethermind/Nethermind.Serialization.Json/ForcedNumberConversion.cs index a4f2ee0cad0..27d95de085e 100644 --- a/src/Nethermind/Nethermind.Serialization.Json/ForcedNumberConversion.cs +++ b/src/Nethermind/Nethermind.Serialization.Json/ForcedNumberConversion.cs @@ -7,7 +7,7 @@ namespace Nethermind.Serialization.Json; public static class ForcedNumberConversion { - public static readonly AsyncLocal ForcedConversion = new(null); + public static readonly AsyncLocal ForcedConversion = new(); public static NumberConversion GetFinalConversion() => ForcedConversion.Value ?? NumberConversion.Hex; }