diff --git a/Directory.Packages.props b/Directory.Packages.props
index 460430443d4..28655cec999 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -72,6 +72,7 @@
+
@@ -89,4 +90,4 @@
-
+
\ No newline at end of file
diff --git a/src/Nethermind/Nethermind.Blockchain/CanonicalStateRootFinder.cs b/src/Nethermind/Nethermind.Blockchain/CanonicalStateRootFinder.cs
new file mode 100644
index 00000000000..85d46eeb322
--- /dev/null
+++ b/src/Nethermind/Nethermind.Blockchain/CanonicalStateRootFinder.cs
@@ -0,0 +1,17 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.State.Flat;
+
+namespace Nethermind.Blockchain;
+
+public class CanonicalStateRootFinder(IBlockTree blockTree): ICanonicalStateRootFinder
+{
+ public Hash256? GetCanonicalStateRootAtBlock(long blockNumber)
+ {
+ BlockHeader? header = blockTree.FindHeader(blockNumber, BlockTreeLookupOptions.RequireCanonical);
+ return header?.StateRoot;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs b/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs
index 17b3d97d0a8..8fccf256dd8 100644
--- a/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs
+++ b/src/Nethermind/Nethermind.Consensus/Processing/PrewarmerEnvFactory.cs
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
+using System;
using Autofac;
using Nethermind.Blockchain;
using Nethermind.Core;
diff --git a/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs b/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs
index 529df1fdfc1..0c73783b4bb 100644
--- a/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs
+++ b/src/Nethermind/Nethermind.Core.Test/TestMemColumnDb.cs
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
+using System;
using System.Collections.Generic;
using Nethermind.Db;
@@ -30,6 +31,12 @@ public IColumnsWriteBatch StartWriteBatch()
{
return new InMemoryColumnWriteBatch(this);
}
+
+ public IColumnDbSnapshot CreateSnapshot()
+ {
+ throw new Exception("Snapshot not implemented");
+ }
+
public void Dispose() { }
public void Flush(bool onlyWal = false) { }
}
diff --git a/src/Nethermind/Nethermind.Core/Account.cs b/src/Nethermind/Nethermind.Core/Account.cs
index ab7b335ff02..960e424ff73 100644
--- a/src/Nethermind/Nethermind.Core/Account.cs
+++ b/src/Nethermind/Nethermind.Core/Account.cs
@@ -127,6 +127,11 @@ public Account WithChangedCodeHash(Hash256 newCodeHash)
}
public AccountStruct ToStruct() => new(Nonce, Balance, StorageRoot, CodeHash);
+
+ public override string ToString()
+ {
+ return $"N:{Nonce},B:{Balance},S{StorageRoot},C:{CodeHash}";
+ }
}
public readonly struct AccountStruct : IEquatable
diff --git a/src/Nethermind/Nethermind.Core/Address.cs b/src/Nethermind/Nethermind.Core/Address.cs
index d20e96be38d..aefc77c27eb 100644
--- a/src/Nethermind/Nethermind.Core/Address.cs
+++ b/src/Nethermind/Nethermind.Core/Address.cs
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System;
+using System.Buffers.Binary;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
diff --git a/src/Nethermind/Nethermind.Core/Crypto/Hash256.cs b/src/Nethermind/Nethermind.Core/Crypto/Hash256.cs
index 892e20e6c10..f5af01218a8 100644
--- a/src/Nethermind/Nethermind.Core/Crypto/Hash256.cs
+++ b/src/Nethermind/Nethermind.Core/Crypto/Hash256.cs
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System;
+using System.Buffers.Binary;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -113,7 +114,12 @@ public readonly struct Hash256AsKey(Hash256 key) : IEquatable, ICo
public bool Equals(Hash256AsKey other) => Equals(_key, other._key);
public override int GetHashCode() => _key?.GetHashCode() ?? 0;
- public int CompareTo(Hash256AsKey other) => _key.CompareTo(other._key);
+ public int CompareTo(Hash256AsKey other)
+ {
+ if (_key is null && other._key is not null) return -1;
+ if (_key is null && other._key is null) return 0;
+ return _key!.CompareTo(other._key);
+ }
}
[DebuggerStepThrough]
diff --git a/src/Nethermind/Nethermind.Core/DevMetric.cs b/src/Nethermind/Nethermind.Core/DevMetric.cs
new file mode 100644
index 00000000000..066c6f98da6
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/DevMetric.cs
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Prometheus;
+
+namespace Nethermind.Core;
+
+public static class DevMetric
+{
+ public static MetricFactory Factory = Prometheus.Metrics.WithCustomRegistry(Prometheus.Metrics.NewCustomRegistry()); // Custom registry does not publish by default
+ // public static MetricFactory Factory = Prometheus.Metrics.DefaultFactory;
+}
diff --git a/src/Nethermind/Nethermind.Core/IKeyValueStore.cs b/src/Nethermind/Nethermind.Core/IKeyValueStore.cs
index 52a6b97b317..783857d58e9 100644
--- a/src/Nethermind/Nethermind.Core/IKeyValueStore.cs
+++ b/src/Nethermind/Nethermind.Core/IKeyValueStore.cs
@@ -74,7 +74,7 @@ public interface IMergeableKeyValueStore : IWriteOnlyKeyValueStore
void Merge(ReadOnlySpan key, ReadOnlySpan value, WriteFlags flags = WriteFlags.None);
}
- public interface ISortedKeyValueStore : IKeyValueStore
+ public interface ISortedKeyValueStore : IReadOnlyKeyValueStore
{
byte[]? FirstKey { get; }
byte[]? LastKey { get; }
diff --git a/src/Nethermind/Nethermind.Core/Nethermind.Core.csproj b/src/Nethermind/Nethermind.Core/Nethermind.Core.csproj
index 54af4e25feb..a62645e96c8 100644
--- a/src/Nethermind/Nethermind.Core/Nethermind.Core.csproj
+++ b/src/Nethermind/Nethermind.Core/Nethermind.Core.csproj
@@ -14,6 +14,7 @@
+
diff --git a/src/Nethermind/Nethermind.Core/Utils/RefCountingDisposable.cs b/src/Nethermind/Nethermind.Core/Utils/RefCountingDisposable.cs
new file mode 100644
index 00000000000..7ae884455cf
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Utils/RefCountingDisposable.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace Nethermind.Core.Utils;
+
+///
+/// Provides a component that can be disposed multiple times and runs only on the last dispose.
+///
+public abstract class RefCountingDisposable : IDisposable
+{
+ private const int Single = 1;
+ private const int NoAccessors = 0;
+ private const int Disposing = -1;
+
+ protected PaddedValue _leases;
+
+ protected RefCountingDisposable(int initialCount = Single)
+ {
+ _leases.Value = initialCount;
+ }
+
+ public void AcquireLease()
+ {
+ if (TryAcquireLease() == false)
+ {
+ ThrowCouldNotAcquire();
+ }
+
+ [DoesNotReturn]
+ [StackTraceHidden]
+ static void ThrowCouldNotAcquire()
+ {
+ throw new Exception("The lease cannot be acquired");
+ }
+ }
+
+ protected bool TryAcquireLease()
+ {
+ // Volatile read for starting value
+ var current = Volatile.Read(ref _leases.Value);
+ if (current == Disposing)
+ {
+ // Already disposed
+ return false;
+ }
+
+ while (true)
+ {
+ var prev = Interlocked.CompareExchange(ref _leases.Value, current + Single, current);
+ if (prev == current)
+ {
+ // Successfully acquired
+ return true;
+ }
+ if (prev == Disposing)
+ {
+ // Already disposed
+ return false;
+ }
+
+ // Try again with new starting value
+ current = prev;
+ // Add PAUSE instruction to reduce shared core contention
+ Thread.SpinWait(1);
+ }
+ }
+
+ ///
+ /// Disposes it once, decreasing the lease count by 1.
+ ///
+ public void Dispose() => ReleaseLeaseOnce();
+
+ private void ReleaseLeaseOnce()
+ {
+ // Volatile read for starting value
+ var current = Volatile.Read(ref _leases.Value);
+ if (current <= NoAccessors)
+ {
+ // Mismatched Acquire/Release
+ ThrowOverDisposed();
+ }
+
+ while (true)
+ {
+ var prev = Interlocked.CompareExchange(ref _leases.Value, current - Single, current);
+ if (prev != current)
+ {
+ current = prev;
+ // Add PAUSE instruction to reduce shared core contention
+ Thread.SpinWait(1);
+ continue;
+ }
+ if (prev == Single)
+ {
+ // Last use, try to dispose underlying
+ break;
+ }
+ if (prev <= NoAccessors)
+ {
+ // Mismatched Acquire/Release
+ ThrowOverDisposed();
+ }
+
+ // Successfully released
+ return;
+ }
+
+ if (Interlocked.CompareExchange(ref _leases.Value, Disposing, NoAccessors) == NoAccessors)
+ {
+ // set to disposed by this Release
+ CleanUp();
+ }
+
+ [DoesNotReturn]
+ [StackTraceHidden]
+ static void ThrowOverDisposed()
+ {
+ throw new Exception("The lease has already been disposed");
+ }
+ }
+
+ protected abstract void CleanUp();
+
+ public override string ToString()
+ {
+ var leases = Volatile.Read(ref _leases.Value);
+ return leases == Disposing ? "Disposed" : $"Leases: {leases}";
+ }
+
+ [StructLayout(LayoutKind.Explicit, Size = 128)]
+ protected struct PaddedValue
+ {
+ [FieldOffset(64)]
+ public long Value;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Core/Utils/RefCountingDisposableBox.cs b/src/Nethermind/Nethermind.Core/Utils/RefCountingDisposableBox.cs
new file mode 100644
index 00000000000..8431f752115
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Utils/RefCountingDisposableBox.cs
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+
+namespace Nethermind.Core.Utils;
+
+public class RefCountingDisposableBox(T item): RefCountingDisposable
+ where T : IDisposable
+{
+
+ public T Item => item;
+
+ public bool TryAcquire()
+ {
+ return TryAcquireLease();
+ }
+
+ protected override void CleanUp()
+ {
+ Item.Dispose();
+ }
+}
diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs
index 34713b992b7..4c2890960ec 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs
@@ -83,6 +83,19 @@ public IEnumerable GetAllValues(bool ordered = false)
return _mainDb.GetAllValuesCore(iterator);
}
+ public IDbSnapshot CreateSnapshot()
+ {
+ ReadOptions readOptions = new();
+ Snapshot snapshot = _mainDb._db.CreateSnapshot();
+ readOptions.SetSnapshot(snapshot);
+
+ return new DbOnTheRocks.DbSnapshot(
+ _mainDb,
+ readOptions,
+ _columnFamily,
+ snapshot);
+ }
+
public IWriteBatch StartWriteBatch()
{
return new ColumnsDbWriteBatch(this, (DbOnTheRocks.RocksDbWriteBatch)_mainDb.StartWriteBatch());
diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs
index 5a83aa1483b..21239cc0371 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnsDb.cs
@@ -4,8 +4,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.InteropServices;
using FastEnumUtility;
using Nethermind.Core;
+using Nethermind.Core.Extensions;
using Nethermind.Db.Rocks.Config;
using Nethermind.Logging;
using RocksDbSharp;
@@ -156,4 +158,32 @@ public void Merge(ReadOnlySpan key, ReadOnlySpan value, WriteFlags f
_writeBatch._writeBatch.Merge(key, value, _column._columnFamily, flags);
}
}
+
+ IColumnDbSnapshot IColumnsDb.CreateSnapshot()
+ {
+ Snapshot snapshot = _db.CreateSnapshot();
+ return new ColumnDbSnapshot(this, snapshot);
+ }
+
+ private class ColumnDbSnapshot(
+ ColumnsDb columnsDb,
+ Snapshot snapshot
+ ) : IColumnDbSnapshot
+ {
+ public IReadOnlyKeyValueStore GetColumn(T key)
+ {
+ ReadOptions options = new ReadOptions();
+ options.SetSnapshot(snapshot);
+ return new DbOnTheRocks.DbSnapshot(
+ columnsDb,
+ options,
+ columnsDb._columnDbs[key]._columnFamily,
+ snapshot);
+ }
+
+ public void Dispose()
+ {
+ snapshot.Dispose();
+ }
+ }
}
diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs
index f0efb6213da..35e454b0f75 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs
@@ -16,10 +16,24 @@ public class DbConfig : IDbConfig
public bool EnableDbStatistics { get; set; } = false;
public bool EnableMetricsUpdater { get; set; } = false;
public uint StatsDumpPeriodSec { get; set; } = 600;
+ public bool SkipDefaultDbOptions { get; set; } = false;
public int? MaxOpenFiles { get; set; }
public ulong? ReadAheadSize { get; set; } = (ulong)256.KiB();
+
+ private const string MinimumBasicOption =
+ "target_file_size_base=64000000;" +
+ "max_bytes_for_level_base=256000000;" +
+ "write_buffer_size=250000000;" +
+ "min_write_buffer_number_to_merge=1;" +
+ "max_write_buffer_number=2;" +
+ "max_compaction_bytes=4000000000;" +
+ "memtable_whole_key_filtering=true;" +
+ "memtable_prefix_bloom_size_ratio=0.02;" +
+ "advise_random_on_open=true;" +
+ "";
+
public string RocksDbOptions { get; set; } =
// This section affect the write buffer, or memtable. Note, the size of write buffer affect the size of l0
@@ -41,7 +55,11 @@ public class DbConfig : IDbConfig
"max_compaction_bytes=4000000000;" +
"compression=kSnappyCompression;" +
- "optimize_filters_for_hits=true;" +
+
+ // Note, if this is set, then other Db cannot override it. It save a little bit of space by not creating
+ // bloom filter for the last level.
+ // "optimize_filters_for_hits=true;"
+
"advise_random_on_open=true;" +
// Target size of each SST file. Increase to reduce number of file. Default is 64MB.
@@ -170,6 +188,8 @@ public class DbConfig : IDbConfig
"allow_concurrent_memtable_write=false;";
public string? CodeDbAdditionalRocksDbOptions { get; set; }
+ public ulong? MetadataDbRowCacheSize { get; set; }
+
public string BloomDbRocksDbOptions { get; set; } =
"max_bytes_for_level_base=16000000;";
public string? BloomDbAdditionalRocksDbOptions { get; set; }
@@ -181,7 +201,7 @@ public class DbConfig : IDbConfig
public ulong StateDbWriteBufferSize { get; set; } = (ulong)64.MB();
public ulong StateDbWriteBufferNumber { get; set; } = 4;
- public bool? StateDbVerifyChecksum { get; set; }
+ public bool? StateDbVerifyChecksum { get; set; } = true;
public ulong? StateDbRowCacheSize { get; set; }
public bool StateDbEnableFileWarmer { get; set; } = false;
public double StateDbCompressibilityHint { get; set; } = 0.45;
@@ -228,11 +248,13 @@ public class DbConfig : IDbConfig
// Note: This causes write batch to not be atomic. A concurrent read may read item on start of batch, but not end of batch.
// With state, this is fine as writes are done in parallel batch and therefore, not atomic, and the read goes
// through triestore first anyway.
- "unordered_write=true;" +
+ // "unordered_write=true;" +
// Default is 1 MB.
"max_write_batch_group_size_bytes=4000000;" +
+ "optimize_filters_for_hits=true;" +
+
"";
public string StateDbLargeMemoryRocksDbOptions { get; set; } =
@@ -270,4 +292,224 @@ public class DbConfig : IDbConfig
public string L1OriginDbRocksDbOptions { get; set; } = "";
public string? L1OriginDbAdditionalRocksDbOptions { get; set; }
+
+
+ public ulong FlatDbWriteBufferSize { get; set; } = (ulong)64.MB();
+ public ulong FlatDbWriteBufferNumber { get; set; } = 4;
+ public bool? FlatDbVerifyChecksum { get; set; } = false; // YOLO
+ public bool FlatDbEnableFileWarmer { get; set; }
+ public string FlatDbRocksDbOptions { get; set; } =
+ MinimumBasicOption +
+
+ // This is basically useless on write only database. However, for halfpath with live pruning, flatdb, or
+ // (maybe?) full sync where keys are deleted, replaced, or re-inserted, two memtable can merge together
+ // resulting in a reduced total memtable size to be written. This does seems to reduce sync throughput though.
+ "min_write_buffer_number_to_merge=2;" +
+
+ // Default value is 16.
+ // So each block consist of several "restart" and each "restart" is BlockRestartInterval number of key.
+ // They key within the same restart is delta-encoded with the key before it. This mean a read will have to go
+ // through potentially "BlockRestartInterval" number of key, probably. That is my understanding.
+ // Reducing this is likely going to improve CPU usage at the cost of increased uncompressed size, which effect
+ // cache utilization.
+ "block_based_table_factory.block_restart_interval=4;" +
+
+ // This adds a hashtable-like index per block (the 32kb block)
+ // This reduce CPU and therefore latency under high block cache hit scenario.
+ // It seems to increase disk space use by about 1 GB.
+ "block_based_table_factory.data_block_index_type=kDataBlockBinaryAndHash;" +
+ "block_based_table_factory.data_block_hash_table_util_ratio=0.7;" +
+
+ "block_based_table_factory.block_size=16000;" +
+
+ "block_based_table_factory.filter_policy=bloomfilter:15;" +
+
+ // Default is 1 MB.
+ "max_write_batch_group_size_bytes=4000000;" +
+
+ "";
+ public string? FlatDbAdditionalRocksDbOptions { get; set; }
+
+ public string? FlatMetadataDbRocksDbOptions { get; set; } =
+ MinimumBasicOption +
+ // This adds a hashtable-like index per block (the 32kb block)
+ // This reduce CPU and therefore latency under high block cache hit scenario.
+ // It seems to increase disk space use by about 1 GB.
+ "block_based_table_factory.data_block_index_type=kDataBlockBinaryAndHash;" +
+ "block_based_table_factory.data_block_hash_table_util_ratio=0.7;" +
+ "compression=kNoCompression;" +
+
+ "";
+ public ulong? FlatMetadataDbRowCacheSize { get; set; } = (ulong?)1.MiB();
+ public string? FlatMetadataDbAdditionalRocksDbOptions { get; set; }
+ public bool? FlatStateDbVerifyChecksum { get; set; } = false; // YOLO
+
+ public bool FlatStateDbEnableFileWarmer { get; set; } = false;
+ public ulong FlatStateDbWriteBufferSize { get; set; } = (ulong)64.MiB();
+ public ulong FlatStateDbRowCacheSize { get; set; } = 0;
+ public ulong FlatStateDbWriteBufferNumber { get; set; } = 4;
+ public bool FlatStateDbSkipDefaultDbOptions { get; set; } = true;
+
+ private const string FlatCommonConfigWithPlainTable =
+ MinimumBasicOption +
+ "memtable=prefix_hash:1000;" +
+
+ "min_write_buffer_number_to_merge=2;" +
+
+ // This used to be on trie, but its here now. Attempt to reduce LSM depth at cost of write amp.
+ "max_bytes_for_level_multiplier=30;" +
+ "max_bytes_for_level_base=350000000;" +
+ "plain_table_factory={};" +
+ "";
+
+ private const string FlatCommonConfigWithBlockBased =
+ MinimumBasicOption +
+
+ // Hard to decide. No compression is lower latency. But it means bigger db, which means worst cache is at os
+ // level. TODO: Measure how much the db size change.
+ // "compression=kNoCompression;" +
+
+ "compression=kLZ4Compression;" +
+
+ // "memtable=prefix_hash:1000;" +
+ "memtable=skiplist;" +
+ "max_write_buffer_number=4;" +
+ "min_write_buffer_number_to_merge=2;" +
+ "wal_compression=kZSTD;" + // I think it does not work.
+
+ // This used to be on trie, but its here now. Attempt to reduce LSM depth at cost of write amp.
+ "max_bytes_for_level_multiplier=20;" +
+ "max_bytes_for_level_base=250000000;" +
+
+ "block_based_table_factory.metadata_block_size=4096;" +
+ "block_based_table_factory.block_restart_interval=4;" +
+ "block_based_table_factory.data_block_index_type=kDataBlockBinaryAndHash;" +
+ "block_based_table_factory.data_block_hash_table_util_ratio=0.7;" +
+ "block_based_table_factory.prepopulate_block_cache=kFlushOnly;" +
+ "block_based_table_factory.pin_l0_filter_and_index_blocks_in_cache=true;" +
+ "block_based_table_factory.cache_index_and_filter_blocks_with_high_priority=true;" +
+ "block_based_table_factory.whole_key_filtering=true;" + // should be default. Just in case.
+
+ // Important tunables
+
+ // Further split bloom filter. Reduces memory but add latency. Set to false now
+ // "block_based_table_factory.partition_filters=true;" +
+
+ // Smaller block size is faster to load slightly. But on most SSD, any value lower than a certain number
+ // around 16k, does not reduce latency much. The important impact is memory, as lower block size mean more
+ // hot block can fit in memory, but at the same time, index size become larger, which may take up more memory.
+ "block_based_table_factory.block_size=4096;" +
+
+ // Two level index means only the top level index points to another index before pointing to block.
+ // Only top level index is in memory all the time. This adds latency, but reduces memory usage.
+ // "block_based_table_factory.index_type=kTwoLevelIndexSearch;" +
+
+ // Complete bsearch index in memory
+ "block_based_table_factory.index_type=kBinarySearch;" +
+
+ // This **should** help given prefix extractor. But further increase index size.
+ // "block_based_table_factory.index_type=kHashSearch;" +
+
+ // So that last level bloom is kept. Should accelerate miss state check.
+ "optimize_filters_for_hits=false;" +
+ "";
+
+ public const string FlatCommonConfig = FlatCommonConfigWithBlockBased;
+
+ // Note: No prefix extractor for state.Dont forget.
+ public string? FlatStateDbRocksDbOptions { get; set; } =
+ FlatCommonConfig +
+ // "use_direct_reads=true;" + // For testing
+ // "prefix_extractor=capped:3;" + // I forget why.
+ "block_based_table_factory.block_cache=64000000;" +
+ "block_based_table_factory.filter_policy=ribbonfilter:12;" +
+ "";
+
+ public string? FlatStateDbAdditionalRocksDbOptions { get; set; }
+ public bool? FlatStorageDbVerifyChecksum { get; set; }
+ public bool FlatStorageDbSkipDefaultDbOptions { get; set; } = true;
+ public bool FlatStorageDbEnableFileWarmer { get; set; }
+ public ulong FlatStorageDbRowCacheSize { get; set; } = 0;
+ public ulong FlatStorageDbWriteBufferSize { get; set; }= (ulong)64.MiB();
+ public ulong FlatStorageDbWriteBufferNumber { get; set; } = 4;
+
+ public string? FlatStorageDbRocksDbOptions { get; set; } =
+ FlatCommonConfig +
+ // v"plain_table_factory={user_key_len=52;};" +
+ // "block_based_table_factory.index_type=kBinarySearch;" +
+ // "block_based_table_factory.block_restart_interval=6;" + // For storage the prefix have a lot in common.
+ // "memtable=skiplist;" +
+ // "prefix_extractor=capped:23;" + // 20 byte address + 3 byte prefix.
+ // "use_direct_reads=true;" + // For testing
+ "block_based_table_factory.block_cache=500000000;" +
+ "block_based_table_factory.block_size=16000;" + // Using 4kb size is faster, IO wise, but uses additional 500 MB of memory, which if put on block cache is much betterr.
+ "block_based_table_factory.filter_policy=ribbonfilter:8;" +
+ "";
+
+ public string? FlatStorageDbAdditionalRocksDbOptions { get; set; }
+
+ // Largely the same as statedb, but more write focused.
+ private const string TrieNodeConfig =
+
+ // "use_direct_reads=true;" +
+ // For trie which is heavy in compaction. Use direct io to prevent taking up space in os cache.
+ "use_direct_io_for_flush_and_compaction=true;" +
+
+ // LZ4 seems to be slightly faster here
+ "compression=kLZ4Compression;" +
+
+ "wal_compression=kZSTD;" +
+
+ // Default value is 16.
+ // So each block consist of several "restart" and each "restart" is BlockRestartInterval number of key.
+ // They key within the same restart is delta-encoded with the key before it. This mean a read will have to go
+ // through potentially "BlockRestartInterval" number of key, probably. That is my understanding.
+ // Reducing this is likely going to improve CPU usage at the cost of increased uncompressed size, which effect
+ // cache utilization.
+ "block_based_table_factory.block_restart_interval=8;" +
+
+ // This adds a hashtable-like index per block (the 32kb block)
+ // This reduce CPU and therefore latency under high block cache hit scenario.
+ // It seems to increase disk space use by about 1 GB.
+ "block_based_table_factory.data_block_index_type=kDataBlockBinaryAndHash;" +
+ "block_based_table_factory.data_block_hash_table_util_ratio=0.75;" +
+
+ "block_based_table_factory.block_size=32000;" +
+ "block_based_table_factory.filter_policy=ribbonfilter:15;" +
+
+ // Make it
+ // "optimize_filters_for_hits=true;" +
+ "optimize_filters_for_hits=true;" +
+
+ "";
+
+ // Only 1 gig in total, but almost 1/3rd of the writes.
+ public ulong FlatStateTopNodesDbWriteBufferSize { get; set; } = (ulong)128.MiB();
+ public ulong FlatStateTopNodesDbWriteBufferNumber { get; set; } = 4;
+ public string? FlatStateTopNodesDbRocksDbOptions { get; set; } =
+ TrieNodeConfig +
+ "";
+
+ public ulong FlatStateNodesDbWriteBufferSize { get; set; } = (ulong)128.MiB();
+ public ulong FlatStateNodesDbWriteBufferNumber { get; set; } = 4;
+ public string? FlatStateNodesDbRocksDbOptions { get; set; } =
+ TrieNodeConfig +
+ "";
+ public string? FlatStateTopNodesDbAdditionalRocksDbOptions { get; set; }
+
+ public string? FlatStateNodesDbAdditionalRocksDbOptions { get; set; }
+ public ulong FlatStorageNodesDbWriteBufferSize { get; set; } = (ulong)64.MiB();
+ public ulong FlatStorageNodesDbWriteBufferNumber { get; set; } = 4;
+ public string? FlatStorageNodesDbRocksDbOptions { get; set; } =
+ TrieNodeConfig +
+ "";
+ public string? FlatStorageNodesDbAdditionalRocksDbOptions { get; set; }
+
+ public ulong FlatStorageTopNodesDbWriteBufferSize { get; set; } = (ulong)64.MiB();
+ public ulong FlatStorageTopNodesNodesDbWriteBufferNumber { get; set; } = 4;
+ public string? FlatStorageTopNodesNodesDbRocksDbOptions { get; set; } =
+ TrieNodeConfig +
+ "";
+ public string? FlatStorageTopNodesNodesDbAdditionalRocksDbOptions { get; set; }
+ public ulong PreimageDbWriteBufferSize { get; set; } = (ulong)16.MiB();
}
diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs
index bdd18bb3afd..dd8a003f273 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs
@@ -33,6 +33,7 @@ public interface IDbConfig : IConfig
bool EnableFileWarmer { get; set; }
double CompressibilityHint { get; set; }
bool FlushOnExit { get; set; }
+ bool SkipDefaultDbOptions { get; set; }
string BadBlocksDbRocksDbOptions { get; set; }
string? BadBlocksDbAdditionalRocksDbOptions { get; set; }
@@ -75,6 +76,7 @@ public interface IDbConfig : IConfig
string MetadataDbRocksDbOptions { get; set; }
string? MetadataDbAdditionalRocksDbOptions { get; set; }
+ ulong? MetadataDbRowCacheSize { get; set; }
string BloomDbRocksDbOptions { get; set; }
string? BloomDbAdditionalRocksDbOptions { get; set; }
@@ -101,4 +103,54 @@ public interface IDbConfig : IConfig
string L1OriginDbRocksDbOptions { get; set; }
string? L1OriginDbAdditionalRocksDbOptions { get; set; }
+
+ ulong FlatDbWriteBufferSize { get; set; }
+ ulong FlatDbWriteBufferNumber { get; set; }
+ bool? FlatDbVerifyChecksum { get; set; }
+ bool FlatDbEnableFileWarmer { get; set; }
+ string FlatDbRocksDbOptions { get; set; }
+ string? FlatDbAdditionalRocksDbOptions { get; set; }
+
+ string? FlatMetadataDbRocksDbOptions { get; set; }
+ ulong? FlatMetadataDbRowCacheSize { get; set; }
+ string? FlatMetadataDbAdditionalRocksDbOptions { get; set; }
+
+ bool? FlatStateDbVerifyChecksum { get; set; }
+ bool FlatStateDbSkipDefaultDbOptions { get; set; }
+ bool FlatStateDbEnableFileWarmer { get; set; }
+ ulong FlatStateDbWriteBufferSize { get; set; }
+ ulong FlatStateDbRowCacheSize { get; set; }
+ ulong FlatStateDbWriteBufferNumber { get; set; }
+ string? FlatStateDbRocksDbOptions { get; set; }
+ string? FlatStateDbAdditionalRocksDbOptions { get; set; }
+
+ bool? FlatStorageDbVerifyChecksum { get; set; }
+ bool FlatStorageDbSkipDefaultDbOptions { get; set; }
+ bool FlatStorageDbEnableFileWarmer { get; set; }
+ ulong FlatStorageDbRowCacheSize { get; set; }
+ ulong FlatStorageDbWriteBufferSize { get; set; }
+ ulong FlatStorageDbWriteBufferNumber { get; set; }
+ string? FlatStorageDbRocksDbOptions { get; set; }
+ string? FlatStorageDbAdditionalRocksDbOptions { get; set; }
+
+ ulong FlatStateNodesDbWriteBufferSize { get; set; }
+ ulong FlatStateNodesDbWriteBufferNumber { get; set; }
+ string? FlatStateNodesDbRocksDbOptions { get; set; }
+ string? FlatStateNodesDbAdditionalRocksDbOptions { get; set; }
+
+ ulong FlatStateTopNodesDbWriteBufferSize { get; set; }
+ ulong FlatStateTopNodesDbWriteBufferNumber { get; set; }
+ string? FlatStateTopNodesDbRocksDbOptions { get; set; }
+ string? FlatStateTopNodesDbAdditionalRocksDbOptions { get; set; }
+
+ ulong FlatStorageNodesDbWriteBufferSize { get; set; }
+ ulong FlatStorageNodesDbWriteBufferNumber { get; set; }
+ string? FlatStorageNodesDbRocksDbOptions { get; set; }
+ string? FlatStorageNodesDbAdditionalRocksDbOptions { get; set; }
+
+ ulong FlatStorageTopNodesDbWriteBufferSize { get; set; }
+ ulong FlatStorageTopNodesNodesDbWriteBufferNumber { get; set; }
+ string? FlatStorageTopNodesNodesDbRocksDbOptions { get; set; }
+ string? FlatStorageTopNodesNodesDbAdditionalRocksDbOptions { get; set; }
+ ulong PreimageDbWriteBufferSize { get; set; }
}
diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs
index f70d96006d3..4e10ea15173 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IRocksDbConfig.cs
@@ -7,6 +7,7 @@ public interface IRocksDbConfig
{
ulong? WriteBufferSize { get; }
ulong? WriteBufferNumber { get; }
+ bool SkipDefaultDbOptions => false;
string RocksDbOptions { get; }
string AdditionalRocksDbOptions { get; }
int? MaxOpenFiles { get; }
diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs
index 0efa1fe7553..06c4c4f7bb8 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs
@@ -48,12 +48,14 @@ private void EnsureConfigIsAvailable(string propertyName)
public ulong? WriteBufferSize => ReadConfig(nameof(WriteBufferSize));
public ulong? WriteBufferNumber => ReadConfig(nameof(WriteBufferNumber));
- public string RocksDbOptions => ReadRocksdbOptions(_dbConfig, nameof(RocksDbOptions), _prefixes);
- public string AdditionalRocksDbOptions => ReadRocksdbOptions(_dbConfig, nameof(AdditionalRocksDbOptions), _prefixes);
+ public string RocksDbOptions => ReadRocksdbOptions(_dbConfig, nameof(RocksDbOptions), _prefixes, SkipDefaultDbOptions);
+
+ public string AdditionalRocksDbOptions => ReadRocksdbOptions(_dbConfig, nameof(AdditionalRocksDbOptions), _prefixes, SkipDefaultDbOptions);
public int? MaxOpenFiles => ReadConfig(nameof(MaxOpenFiles));
public bool WriteAheadLogSync => ReadConfig(nameof(WriteAheadLogSync));
public ulong? ReadAheadSize => ReadConfig(nameof(ReadAheadSize));
+ public bool SkipDefaultDbOptions => ReadConfig(nameof(SkipDefaultDbOptions));
public bool EnableDbStatistics => _dbConfig.EnableDbStatistics;
public uint StatsDumpPeriodSec => _dbConfig.StatsDumpPeriodSec;
public bool? VerifyChecksum => ReadConfig(nameof(VerifyChecksum));
@@ -85,12 +87,14 @@ private string[] GetPrefixes()
return [string.Concat(_tableName, "Db")];
}
- private static string ReadRocksdbOptions(IDbConfig dbConfig, string propertyName, string[] prefixes)
+ private static string ReadRocksdbOptions(IDbConfig dbConfig, string propertyName, string[] prefixes, bool skipDefault)
{
Type type = dbConfig.GetType();
PropertyInfo? propertyInfo;
- string val = (string)GetProperty(type, propertyName)!.GetValue(dbConfig)!;
+ string val = skipDefault
+ ? ""
+ : (string)GetProperty(type, propertyName)!.GetValue(dbConfig)!;
foreach (var prefix in prefixes)
{
diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs
index a69d62475f0..b96249b08bf 100644
--- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs
+++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs
@@ -29,7 +29,7 @@
namespace Nethermind.Db.Rocks;
-public partial class DbOnTheRocks : IDb, ITunableDb, IReadOnlyNativeKeyValueStore, ISortedKeyValueStore, IMergeableKeyValueStore
+public partial class DbOnTheRocks : IDb, ITunableDb, IReadOnlyNativeKeyValueStore, ISnapshottableKeyValueStore, ISortedKeyValueStore, IMergeableKeyValueStore
{
protected ILogger _logger;
@@ -199,6 +199,29 @@ private RocksDb Init(string basePath, string dbPath, IDbConfig dbConfig, ILogMan
WarmupFile(_fullPath, db);
}
+ /*
+ if (Name == "FlatState")
+ {
+ Console.Error.WriteLine("Reading all from flat state");
+ long keyCount = 0;
+ using (var it = db.NewIterator())
+ {
+ it.SeekToFirst();
+
+ while (it.Valid())
+ {
+ keyCount++;
+ if (keyCount % 1000000 == 0)
+ {
+ Console.Error.WriteLine($"{keyCount} keys");
+ }
+ it.Next();
+ }
+ }
+ Console.Error.WriteLine($"{keyCount} keys");
+ }
+ */
+
return db;
}
catch (DllNotFoundException e) when (e.Message.Contains("libdl"))
@@ -215,7 +238,6 @@ private RocksDb Init(string basePath, string dbPath, IDbConfig dbConfig, ILogMan
CreateMarkerIfCorrupt(x);
throw;
}
-
}
private void WarmupFile(string basePath, RocksDb db)
@@ -250,15 +272,15 @@ private void WarmupFile(string basePath, RocksDb db)
long totalSize = 0;
fileMetadatas = fileMetadatas.TakeWhile(metadata =>
- {
- availableMemory -= (long)metadata.metadata.FileSize;
- bool take = availableMemory > 0;
- if (take)
{
- totalSize += (long)metadata.metadata.FileSize;
- }
- return take;
- })
+ availableMemory -= (long)metadata.metadata.FileSize;
+ bool take = availableMemory > 0;
+ if (take)
+ {
+ totalSize += (long)metadata.metadata.FileSize;
+ }
+ return take;
+ })
// We reverse them again so that lower level goes last so that it is the freshest.
// Not all of the available memory is actually available so we are probably over reading things.
.Reverse()
@@ -436,7 +458,7 @@ private long GetMemtableSize()
return 0;
}
- [GeneratedRegex("(?[^; ]+)\\=(?[^; ]+);", RegexOptions.Singleline | RegexOptions.NonBacktracking | RegexOptions.ExplicitCapture)]
+ [GeneratedRegex("(?[A-Za-z0-9_\\.]+)\\=(?[^; ]+);", RegexOptions.Singleline | RegexOptions.NonBacktracking | RegexOptions.ExplicitCapture)]
private static partial Regex ExtractDbOptionsRegex();
public static IDictionary ExtractOptions(string dbOptions)
@@ -467,8 +489,29 @@ protected virtual void BuildOptions(IRocksDbConfig dbConfig, Options optio
_writeBufferSize = ulong.Parse(optionsAsDict["write_buffer_size"]);
_maxWriteBufferNumber = int.Parse(optionsAsDict["max_write_buffer_number"]);
- BlockBasedTableOptions tableOptions = new();
- options.SetBlockBasedTableFactory(tableOptions);
+ var isUsingPlainTable = optionsAsDict.ContainsKey("plain_table_factory");
+ BlockBasedTableOptions? tableOptions = null;
+ if (isUsingPlainTable)
+ {
+ // It just need to set the default factory.
+ // settings can be changed via the option string later, but this need to be set first.
+ options.SetPlainTableFactory(
+ user_key_len: 0,
+ bloom_bits_per_key: 10,
+ hash_table_ratio: 0.75,
+ index_sparseness: 16,
+ huge_page_tlb_size: 0,
+ encoding_type: (char)0,
+ full_scan_mode: false,
+ store_index_in_file: true
+ );
+ }
+ else
+ {
+ tableOptions = new();
+ options.SetBlockBasedTableFactory(tableOptions);
+ }
+
IntPtr optsPtr = Marshal.StringToHGlobalAnsi(dbConfig.RocksDbOptions);
try
{
@@ -485,7 +528,7 @@ protected virtual void BuildOptions(IRocksDbConfig dbConfig, Options optio
blockCacheSize = ulong.Parse(blockCacheSizeStr);
}
- if (sharedCache is not null && blockCacheSize == 0)
+ if (sharedCache is not null && blockCacheSize == 0 && tableOptions is not null)
{
tableOptions.SetBlockCache(sharedCache.Value);
}
@@ -503,6 +546,8 @@ protected virtual void BuildOptions(IRocksDbConfig dbConfig, Options optio
}
if (_maxWriteBufferNumber < 1) throw new InvalidConfigurationException($"Error initializing {Name} db. Max write buffer number must be more than 1. max write buffer number: {_maxWriteBufferNumber}", ExitCodes.GeneralError);
+ options.SetAllowConcurrentMemtableWrite(false);
+
#endregion
#region WriteBuffer
@@ -707,8 +752,8 @@ public byte[]? this[ReadOnlySpan key]
fixed (byte* ptr = &MemoryMarshal.GetReference(key))
{
handle = cf is null
- ? Native.Instance.rocksdb_get_pinned(db, read_options, ptr, skLength, out errPtr)
- : Native.Instance.rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errPtr);
+ ? Native.Instance.rocksdb_get_pinned(db, read_options, ptr, skLength, out errPtr)
+ : Native.Instance.rocksdb_get_pinned_cf(db, read_options, cf.Handle, ptr, skLength, out errPtr);
}
if (errPtr != IntPtr.Zero) ThrowRocksDbException(errPtr);
@@ -876,7 +921,14 @@ public Span GetSpan(scoped ReadOnlySpan key, ReadFlags flags)
return GetSpanWithColumnFamily(key, null, flags);
}
+
internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, ColumnFamilyHandle? cf, ReadFlags flags)
+ {
+ ReadOptions options = (flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _defaultReadOptions;
+ return GetSpanWithColumnFamily(key, cf, options);
+ }
+
+ internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, ColumnFamilyHandle? cf, ReadOptions readOptions)
{
ObjectDisposedException.ThrowIf(_isDisposing, this);
@@ -884,7 +936,7 @@ internal Span GetSpanWithColumnFamily(scoped ReadOnlySpan key, Colum
try
{
- Span span = _db.GetSpan(key, cf, (flags & ReadFlags.HintCacheMiss) != 0 ? _hintCacheMissOptions : _defaultReadOptions);
+ Span span = _db.GetSpan(key, cf, readOptions);
if (!span.IsNullOrEmpty())
{
@@ -1064,6 +1116,19 @@ public IEnumerable GetAllValues(bool ordered = false)
return GetAllValuesCore(iterator);
}
+ public IDbSnapshot CreateSnapshot()
+ {
+ ReadOptions readOptions = new();
+ Snapshot snapshot = _db.CreateSnapshot();
+ readOptions.SetSnapshot(snapshot);
+
+ return new DbSnapshot(
+ this,
+ readOptions,
+ null,
+ snapshot);
+ }
+
internal IEnumerable GetAllValuesCore(Iterator iterator)
{
try
@@ -1941,4 +2006,84 @@ internal ISortedView GetViewBetween(ReadOnlySpan firstKey, ReadOnlySpan key, ReadFlags flags = ReadFlags.None)
+ {
+ ReadOnlySpan value = default;
+ try
+ {
+ value = GetSpan(key, flags);
+
+ if (value.IsNull()) return null;
+ return value.ToArray();
+ }
+ finally
+ {
+ DangerousReleaseMemory(value);
+ }
+ }
+
+ public Span GetSpan(scoped ReadOnlySpan key, ReadFlags flags = ReadFlags.None)
+ {
+ return mainDb.GetSpanWithColumnFamily(key, columnFamily, options);
+ }
+
+ public void DangerousReleaseMemory(in ReadOnlySpan span)
+ {
+ mainDb.DangerousReleaseMemory(span);
+ }
+
+ public byte[]? FirstKey
+ {
+ get
+ {
+ using Iterator iterator = mainDb.CreateIterator(options);
+ iterator.SeekToFirst();
+ return iterator.Valid() ? iterator.GetKeySpan().ToArray() : null;
+ }
+ }
+
+ public byte[]? LastKey
+ {
+ get
+ {
+ using Iterator iterator = mainDb.CreateIterator(options);
+ iterator.SeekToLast();
+ return iterator.Valid() ? iterator.GetKeySpan().ToArray() : null;
+ }
+ }
+
+ public ISortedView GetViewBetween(ReadOnlySpan firstKey, ReadOnlySpan lastKey)
+ {
+ ReadOptions readOptions = new ReadOptions();
+ readOptions.SetSnapshot(snapshot);
+
+ unsafe
+ {
+ IntPtr iterateLowerBound = Marshal.AllocHGlobal(firstKey.Length);
+ firstKey.CopyTo(new Span(iterateLowerBound.ToPointer(), firstKey.Length));
+ Native.Instance.rocksdb_readoptions_set_iterate_lower_bound(readOptions.Handle, iterateLowerBound, (UIntPtr)firstKey.Length);
+
+ IntPtr iterateUpperBound = Marshal.AllocHGlobal(lastKey.Length);
+ lastKey.CopyTo(new Span(iterateUpperBound.ToPointer(), lastKey.Length));
+ Native.Instance.rocksdb_readoptions_set_iterate_upper_bound(readOptions.Handle, iterateUpperBound, (UIntPtr)lastKey.Length);
+ }
+
+ Iterator iterator = mainDb.CreateIterator(readOptions, columnFamily);
+ return new RocksdbSortedView(iterator);
+ }
+
+ public void Dispose()
+ {
+ snapshot.Dispose();
+ }
+ }
}
diff --git a/src/Nethermind/Nethermind.Db.Rocks/FakeColumnsDb.cs b/src/Nethermind/Nethermind.Db.Rocks/FakeColumnsDb.cs
new file mode 100644
index 00000000000..42fbad7daab
--- /dev/null
+++ b/src/Nethermind/Nethermind.Db.Rocks/FakeColumnsDb.cs
@@ -0,0 +1,85 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Generic;
+using System.Linq;
+using Nethermind.Core;
+
+namespace Nethermind.Db.Rocks;
+
+public class FakeColumnsDb(
+ Dictionary innerDb
+): IColumnsDb where T : notnull
+{
+ public void Flush(bool onlyWal = false)
+ {
+ foreach (var keyValuePair in innerDb)
+ {
+ keyValuePair.Value.Flush(onlyWal);
+ }
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public IDb GetColumnDb(T key)
+ {
+ return innerDb[key];
+ }
+
+ public IEnumerable ColumnKeys => innerDb.Keys;
+ public IColumnsWriteBatch StartWriteBatch()
+ {
+ return new FakeWriteBatch(innerDb);
+ }
+
+ public IColumnDbSnapshot CreateSnapshot()
+ {
+ return new FakeSnapshot(innerDb.ToDictionary((kv) => kv.Key, (kv) =>
+ {
+ return ((ISnapshottableKeyValueStore)kv.Value).CreateSnapshot();
+ }));
+ }
+
+ private class FakeWriteBatch : IColumnsWriteBatch
+ {
+ private Dictionary _innerWriteBatch;
+
+ public FakeWriteBatch(Dictionary innerDb)
+ {
+ _innerWriteBatch = innerDb
+ .ToDictionary((kv) => kv.Key, (kv) => kv.Value.StartWriteBatch());
+ }
+
+ public IWriteBatch GetColumnBatch(T key)
+ {
+ return _innerWriteBatch[key];
+ }
+
+ public void Dispose()
+ {
+ foreach (var keyValuePair in _innerWriteBatch)
+ {
+ keyValuePair.Value.Dispose();
+ }
+ }
+ }
+
+ private class FakeSnapshot(Dictionary innerDb) : IColumnDbSnapshot
+ {
+
+ public IReadOnlyKeyValueStore GetColumn(T key)
+ {
+ return innerDb[key];
+ }
+
+ public void Dispose()
+ {
+ foreach (var keyValuePair in innerDb)
+ {
+ keyValuePair.Value.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs b/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs
index 8ddcde89941..73e0e1e4beb 100644
--- a/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs
+++ b/src/Nethermind/Nethermind.Db.Rpc/RpcColumnsDb.cs
@@ -45,6 +45,12 @@ public IColumnsWriteBatch StartWriteBatch()
{
return new InMemoryColumnWriteBatch(this);
}
+
+ public IColumnDbSnapshot CreateSnapshot()
+ {
+ throw new Exception("Snapshot not implemented");
+ }
+
public void Dispose() { }
public void Flush(bool onlyWal = false) { }
}
diff --git a/src/Nethermind/Nethermind.Db/DbNames.cs b/src/Nethermind/Nethermind.Db/DbNames.cs
index e0f96bbc646..15e0145e7db 100644
--- a/src/Nethermind/Nethermind.Db/DbNames.cs
+++ b/src/Nethermind/Nethermind.Db/DbNames.cs
@@ -7,6 +7,7 @@ public static class DbNames
{
public const string Storage = "storage";
public const string State = "state";
+ public const string Flat = "flat";
public const string Code = "code";
public const string Blocks = "blocks";
public const string Headers = "headers";
@@ -19,5 +20,14 @@ public static class DbNames
public const string BlobTransactions = "blobTransactions";
public const string DiscoveryNodes = "discoveryNodes";
public const string PeersDb = "peers";
+ public const string Preimage = "preimage";
+
+ public const string FlatMetadata = "flatMetadata";
+ public const string FlatState = "flatState";
+ public const string FlatStorage = "flatStorage";
+ public const string FlatStateNodes = "flatStateNodes";
+ public const string FlatStateTopNodes = "flatStateNodesTop";
+ public const string FlatStorageNodes = "flatStorageNodes";
+ public const string FlatStorageTopNodes = "flatStorageTopNodes";
}
}
diff --git a/src/Nethermind/Nethermind.Db/FlatDbConfig.cs b/src/Nethermind/Nethermind.Db/FlatDbConfig.cs
new file mode 100644
index 00000000000..f988971b872
--- /dev/null
+++ b/src/Nethermind/Nethermind.Db/FlatDbConfig.cs
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Config;
+using Nethermind.Core.Extensions;
+
+namespace Nethermind.Db;
+
+public interface IFlatDbConfig: IConfig
+{
+ [ConfigItem(Description = "Enabled", DefaultValue = "false")]
+ bool Enabled { get; set; }
+
+ [ConfigItem(Description = "Import from pruning trie state db", DefaultValue = "false")]
+ bool ImportFromPruningTrieState { get; set; }
+
+ [ConfigItem(Description = "Pruning boundary", DefaultValue = "256")]
+ int PruningBoundary { get; set; }
+
+ [ConfigItem(Description = "Compact size", DefaultValue = "16")]
+ int CompactSize { get; set; }
+
+ [ConfigItem(Description = "Compact interval", DefaultValue = "4")]
+ int CompactInterval { get; set; }
+
+ [ConfigItem(Description = "Max in flight compact job", DefaultValue = "32")]
+ int MaxInFlightCompactJob { get; set; }
+
+ [ConfigItem(Description = "Read with try", DefaultValue = "false")]
+ bool ReadWithTrie { get; set; }
+
+ [ConfigItem(Description = "Verify with trie", DefaultValue = "false")]
+ bool VerifyWithTrie { get; set; }
+
+ [ConfigItem(Description = "Inline compaction", DefaultValue = "false")]
+ bool InlineCompaction { get; set; }
+
+ [ConfigItem(Description = "Trie cache memory target", DefaultValue = "false")]
+ long TrieCacheMemoryTarget { get; set; }
+
+ [ConfigItem(Description = "Disable trie warmer", DefaultValue = "false")]
+ bool DisableTrieWarmer { get; set; }
+
+ [ConfigItem(Description = "Use preimage", DefaultValue = "false")]
+ FlatLayout Layout { get; set; }
+}
+
+public enum FlatLayout
+{
+ Flat,
+ FlatNoSeparateTopStorage,
+ FlatInTrie,
+ PreimageFlat
+}
+
+public class FlatDbConfig: IFlatDbConfig
+{
+ public bool Enabled { get; set; } = false;
+ public bool ImportFromPruningTrieState { get; set; } = false;
+ public int PruningBoundary { get; set; } = 256;
+ public int CompactSize { get; set; } = 16;
+ public int CompactInterval { get; set; } = 4;
+ public int MaxInFlightCompactJob { get; set; } = 32;
+ public bool ReadWithTrie { get; set; } = false;
+ public bool VerifyWithTrie { get; set; } = false;
+ public bool InlineCompaction { get; set; } = false;
+
+ // 1 GB is enough for 10% dirty load. 512 MB is pretty good at around 20%. Without it, then the diff layers on its own have around 35% dirty load.
+ public long TrieCacheMemoryTarget { get; set; } = 512.MiB();
+ public bool DisableTrieWarmer { get; set; } = false;
+ public FlatLayout Layout { get; set; }
+}
diff --git a/src/Nethermind/Nethermind.Db/IColumnsDb.cs b/src/Nethermind/Nethermind.Db/IColumnsDb.cs
index 4f1eddcbd44..5ffddced6ab 100644
--- a/src/Nethermind/Nethermind.Db/IColumnsDb.cs
+++ b/src/Nethermind/Nethermind.Db/IColumnsDb.cs
@@ -13,10 +13,17 @@ public interface IColumnsDb : IDbMeta, IDisposable
IEnumerable ColumnKeys { get; }
public IReadOnlyColumnDb CreateReadOnly(bool createInMemWriteStore) => new ReadOnlyColumnsDb(this, createInMemWriteStore);
IColumnsWriteBatch StartWriteBatch();
+ IColumnDbSnapshot CreateSnapshot();
}
public interface IColumnsWriteBatch : IDisposable
{
IWriteBatch GetColumnBatch(TKey key);
}
+
+
+ public interface IColumnDbSnapshot : IDisposable
+ {
+ IReadOnlyKeyValueStore GetColumn(TKey key);
+ }
}
diff --git a/src/Nethermind/Nethermind.Db/IDb.cs b/src/Nethermind/Nethermind.Db/IDb.cs
index 73f9e4ba171..9b20b4d7836 100644
--- a/src/Nethermind/Nethermind.Db/IDb.cs
+++ b/src/Nethermind/Nethermind.Db/IDb.cs
@@ -18,6 +18,15 @@ public interface IDb : IKeyValueStoreWithBatching, IDbMeta, IDisposable
public IReadOnlyDb CreateReadOnly(bool createInMemWriteStore) => new ReadOnlyDb(this, createInMemWriteStore);
}
+ public interface ISnapshottableKeyValueStore
+ {
+ IDbSnapshot CreateSnapshot();
+ }
+
+ public interface IDbSnapshot: IReadOnlyKeyValueStore, IDisposable
+ {
+ }
+
// Some metadata options
public interface IDbMeta
{
diff --git a/src/Nethermind/Nethermind.Db/MemColumnsDb.cs b/src/Nethermind/Nethermind.Db/MemColumnsDb.cs
index ea37042e51b..e0bd679cfe1 100644
--- a/src/Nethermind/Nethermind.Db/MemColumnsDb.cs
+++ b/src/Nethermind/Nethermind.Db/MemColumnsDb.cs
@@ -38,6 +38,12 @@ public IColumnsWriteBatch StartWriteBatch()
{
return new InMemoryColumnWriteBatch(this);
}
+
+ public IColumnDbSnapshot CreateSnapshot()
+ {
+ throw new Exception("Snapshot not supported");
+ }
+
public void Dispose() { }
public void Flush(bool onlyWal = false) { }
}
diff --git a/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs b/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs
index 3b7bafd750d..0c8483d09e7 100644
--- a/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs
+++ b/src/Nethermind/Nethermind.Db/ReadOnlyColumnsDb.cs
@@ -10,9 +10,11 @@ namespace Nethermind.Db
public class ReadOnlyColumnsDb : IReadOnlyColumnDb, IDisposable
{
private readonly IDictionary _readOnlyColumns;
+ private readonly IColumnsDb _baseColumnDb;
public ReadOnlyColumnsDb(IColumnsDb baseColumnDb, bool createInMemWriteStore)
{
+ _baseColumnDb = baseColumnDb;
_readOnlyColumns = baseColumnDb.ColumnKeys
.Select(key => (key, db: baseColumnDb.GetColumnDb(key).CreateReadOnly(createInMemWriteStore)))
.ToDictionary(it => it.key, it => it.db);
@@ -29,6 +31,11 @@ public IColumnsWriteBatch StartWriteBatch()
return new InMemoryColumnWriteBatch(this);
}
+ public IColumnDbSnapshot CreateSnapshot()
+ {
+ return _baseColumnDb.CreateSnapshot();
+ }
+
public void ClearTempChanges()
{
foreach (KeyValuePair readOnlyColumn in _readOnlyColumns)
diff --git a/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs b/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs
index d69a532c873..5acf06ba432 100644
--- a/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs
+++ b/src/Nethermind/Nethermind.Db/SimpleFilePublicKeyDb.cs
@@ -116,6 +116,10 @@ public void Clear()
public IEnumerable GetAllKeys(bool ordered = false) => _cache.Keys;
public IEnumerable GetAllValues(bool ordered = false) => _cache.Values;
+ public IDbSnapshot CreateSnapshot()
+ {
+ throw new NotImplementedException();
+ }
public IWriteBatch StartWriteBatch()
{
diff --git a/src/Nethermind/Nethermind.Era1/EraStore.cs b/src/Nethermind/Nethermind.Era1/EraStore.cs
index 9086fcd4b06..763a9eaf0f7 100644
--- a/src/Nethermind/Nethermind.Era1/EraStore.cs
+++ b/src/Nethermind/Nethermind.Era1/EraStore.cs
@@ -136,10 +136,11 @@ private EraReader GetReader(long epoch)
return new EraReader(new E2StoreReader(_epochs[epoch]));
}
- private async ValueTask EnsureEpochVerified(long epoch, EraReader reader, CancellationToken cancellation)
+ private ValueTask EnsureEpochVerified(long epoch, EraReader reader, CancellationToken cancellation)
{
if (!(_verifiedEpochs.TryGetValue(epoch, out bool verified) && verified))
{
+ /*
Task checksumTask = Task.Run(() =>
{
ValueHash256 checksum = reader.CalculateChecksum();
@@ -161,9 +162,12 @@ private async ValueTask EnsureEpochVerified(long epoch, EraReader reader, Cancel
});
await Task.WhenAll(checksumTask, accumulatorTask);
+ */
_verifiedEpochs.TryAdd(epoch, true);
}
+
+ return ValueTask.CompletedTask;
}
public long NextEraStart(long blockNumber)
diff --git a/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs b/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs
index 96f1e1d7de8..73c386de9b5 100644
--- a/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs
+++ b/src/Nethermind/Nethermind.Evm/State/IWorldStateScopeProvider.cs
@@ -66,6 +66,8 @@ public interface IScope : IDisposable
/// first.
///
void Commit(long blockNumber);
+
+ void HintSet(Address address);
}
public interface ICodeDb
@@ -89,6 +91,8 @@ public interface IStorageTree
///
///
byte[] Get(in ValueHash256 hash);
+
+ void HintSet(in UInt256 index);
}
public interface IWorldStateWriteBatch : IDisposable
diff --git a/src/Nethermind/Nethermind.Init/Modules/FlatWorldStateModule.cs b/src/Nethermind/Nethermind.Init/Modules/FlatWorldStateModule.cs
new file mode 100644
index 00000000000..700f876ef41
--- /dev/null
+++ b/src/Nethermind/Nethermind.Init/Modules/FlatWorldStateModule.cs
@@ -0,0 +1,106 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Generic;
+using Autofac;
+using Nethermind.Api.Steps;
+using Nethermind.Blockchain;
+using Nethermind.Core;
+using Nethermind.Core.Extensions;
+using Nethermind.Db;
+using Nethermind.Db.Rocks;
+using Nethermind.Init.Steps;
+using Nethermind.State;
+using Nethermind.State.Flat;
+using Nethermind.State.Flat.Importer;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.State.Flat.ScopeProvider;
+
+namespace Nethermind.Init.Modules;
+
+public class FlatWorldStateModule(IFlatDbConfig flatDbConfig): Module
+{
+ protected override void Load(ContainerBuilder builder)
+ {
+ builder.AddSingleton(_ => throw new Exception($"{nameof(MainPruningTrieStoreFactory)} disabled."));
+ builder.AddSingleton(_ => throw new Exception($"{nameof(PruningTrieStateFactory)} disabled."));
+
+ builder
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddColumnDatabase(DbNames.Flat)
+ .AddSingleton()
+
+ // These fake db are workaround for missing metrics with column db. Probably not a good idea though as
+ // a failure in writes in one of the DB will break the db.
+ .AddDatabase(DbNames.Preimage)
+ .AddDatabase(DbNames.FlatMetadata)
+ .AddDatabase(DbNames.FlatState)
+ .AddDatabase(DbNames.FlatStorage)
+ .AddDatabase(DbNames.FlatStateNodes)
+ .AddDatabase(DbNames.FlatStateTopNodes)
+ .AddDatabase(DbNames.FlatStorageNodes)
+ .AddDatabase(DbNames.FlatStorageTopNodes)
+ .AddSingleton>((ctx) =>
+ {
+ return new FakeColumnsDb(new Dictionary()
+ {
+ { FlatDbColumns.Metadata, ctx.ResolveKeyed(DbNames.FlatMetadata) },
+ { FlatDbColumns.State, ctx.ResolveKeyed(DbNames.FlatState) },
+ { FlatDbColumns.Storage, ctx.ResolveKeyed(DbNames.FlatStorage) },
+ { FlatDbColumns.StateNodes, ctx.ResolveKeyed(DbNames.FlatStateNodes) },
+ { FlatDbColumns.StorageNodes, ctx.ResolveKeyed(DbNames.FlatStorageNodes) },
+ { FlatDbColumns.StateTopNodes, ctx.ResolveKeyed(DbNames.FlatStateTopNodes) },
+ { FlatDbColumns.StorageTopNodes, ctx.ResolveKeyed(DbNames.FlatStorageTopNodes) },
+ });
+ })
+
+ .AddSingleton()
+ .AddSingleton((config) => new FlatDiffRepository.Configuration()
+ {
+ Boundary = config.PruningBoundary,
+ CompactSize = config.CompactSize,
+ CompactInterval = config.CompactInterval,
+ MaxInFlightCompactJob = config.MaxInFlightCompactJob,
+ ReadWithTrie = config.ReadWithTrie,
+ VerifyWithTrie = config.VerifyWithTrie,
+ ConcurrentCompactor = 1,
+ TrieCacheMemoryTarget = config.TrieCacheMemoryTarget,
+ InlineCompaction = config.InlineCompaction,
+ DisableTrieWarmer = config.DisableTrieWarmer
+ })
+
+ .AddSingleton((flatDbConfig, ctx) =>
+ {
+ if (
+ flatDbConfig.Layout == FlatLayout.PreimageFlat
+ || flatDbConfig.Layout == FlatLayout.Flat
+ || flatDbConfig.Layout == FlatLayout.FlatNoSeparateTopStorage
+ || flatDbConfig.Layout == FlatLayout.FlatInTrie
+ )
+ {
+ return ctx.Resolve();
+ }
+
+ throw new Exception($"Unsupported layout {flatDbConfig.Layout}");
+ })
+
+ .AddSingleton()
+ .AddSingleton((config) => new RocksdbPersistence.Configuration()
+ {
+ UsePreimage = config.Layout == FlatLayout.PreimageFlat,
+ FlatInTrie = config.Layout == FlatLayout.FlatInTrie,
+ SeparateStorageTop = (config.Layout != FlatLayout.FlatInTrie && config.Layout != FlatLayout.FlatNoSeparateTopStorage)
+ })
+ .AddSingleton();
+
+ if (flatDbConfig.ImportFromPruningTrieState)
+ {
+ builder.AddStep(typeof(ImportFlatDb));
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs b/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs
index 9ff2ea05f82..85102db59f7 100644
--- a/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs
+++ b/src/Nethermind/Nethermind.Init/Modules/NethermindModule.cs
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
+using System;
using System.IO.Abstractions;
using Autofac;
using Nethermind.Abi;
@@ -81,6 +82,9 @@ protected override void Load(ContainerBuilder builder)
{
builder.AddSingleton(NullBlobTxStorage.Instance);
}
+
+ if (configProvider.GetConfig().Enabled)
+ builder.AddModule(new FlatWorldStateModule(configProvider.GetConfig()));
}
// Just a wrapper to make it clear, these three are expected to be available at the time of configurations.
diff --git a/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs b/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs
index 7ee5fe7f62c..dab0a524ecb 100644
--- a/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs
+++ b/src/Nethermind/Nethermind.Init/Modules/PrewarmerModule.cs
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only
+using System;
using Autofac;
using Nethermind.Blockchain;
using Nethermind.Config;
@@ -46,11 +47,12 @@ protected override void Load(ContainerBuilder builder)
.AddDecorator((ctx, worldStateScopeProvider) =>
{
if (worldStateScopeProvider is PrewarmerScopeProvider) return worldStateScopeProvider; // Inner world state
- return new PrewarmerScopeProvider(
+ var worldState = new PrewarmerScopeProvider(
worldStateScopeProvider,
ctx.Resolve(),
populatePreBlockCache: false
);
+ return worldState;
})
.AddDecorator((ctx, originalCodeInfoRepository) =>
{
diff --git a/src/Nethermind/Nethermind.Init/Steps/ImportFlatDb.cs b/src/Nethermind/Nethermind.Init/Steps/ImportFlatDb.cs
new file mode 100644
index 00000000000..3b88e3865da
--- /dev/null
+++ b/src/Nethermind/Nethermind.Init/Steps/ImportFlatDb.cs
@@ -0,0 +1,54 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Threading;
+using System.Threading.Tasks;
+using Nethermind.Api.Steps;
+using Nethermind.Blockchain;
+using Nethermind.Config;
+using Nethermind.Core;
+using Nethermind.Logging;
+using Nethermind.State.Flat;
+using Nethermind.State.Flat.Importer;
+using Nethermind.State.Flat.Persistence;
+using RocksDbSharp;
+
+namespace Nethermind.Init.Steps;
+
+[RunnerStepDependencies(
+ dependencies: [typeof(InitializeBlockTree)],
+ dependents: [typeof(InitializeBlockchain)]
+)]
+public class ImportFlatDb(
+ IBlockTree blockTree,
+ IPersistence persistence,
+ Importer importer,
+ IProcessExitSource exitSource,
+ ILogManager logManager
+): IStep
+{
+ ILogger _logger = logManager.GetClassLogger();
+
+ public Task Execute(CancellationToken cancellationToken)
+ {
+ BlockHeader? head = blockTree.Head?.Header;
+ if (head is null) return Task.CompletedTask;
+
+ using (var reader = persistence.CreateReader())
+ {
+ _logger.Warn($"Current state is {reader.CurrentState}");
+ if (reader.CurrentState.blockNumber > 0)
+ {
+ _logger.Info("Flat db already exist");
+ return Task.CompletedTask;
+ }
+ }
+
+ _logger.Info($"Copying state {head.ToString(BlockHeader.Format.Short)} with state root {head.StateRoot}");
+ importer.Copy(new StateId(head));
+
+ exitSource.Exit(0);
+
+ return Task.CompletedTask;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs
index 9f4026090f6..7bb34b48e65 100644
--- a/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs
+++ b/src/Nethermind/Nethermind.Init/Steps/StartMonitoring.cs
@@ -31,8 +31,8 @@ public class StartMonitoring(
ISyncConfig syncConfig,
IServiceStopper serviceStopper,
ILogManager logManager,
- IMetricsConfig metricsConfig,
- ChainHeadInfoProvider chainHeadInfoProvider
+ IMetricsConfig metricsConfig
+ // ChainHeadInfoProvider chainHeadInfoProvider
) : IStep
{
private readonly ILogger _logger = logManager.GetClassLogger();
@@ -112,16 +112,18 @@ private void UpdateDbMetrics()
{
try
{
- if (Environment.TickCount64 - _lastDbMetricsUpdate < 60_000)
+ if (Environment.TickCount64 - _lastDbMetricsUpdate < 5_000)
{
// Update max every minute
return;
}
+ /*
if (chainHeadInfoProvider.IsProcessingBlock)
{
// Do not update db metrics while processing a block
return;
}
+ */
foreach (KeyValuePair kv in dbTracker.GetAllDbMeta())
{
diff --git a/src/Nethermind/Nethermind.Runner/packages.lock.json b/src/Nethermind/Nethermind.Runner/packages.lock.json
index de5f39f1097..1274c31178e 100644
--- a/src/Nethermind/Nethermind.Runner/packages.lock.json
+++ b/src/Nethermind/Nethermind.Runner/packages.lock.json
@@ -21,7 +21,10 @@
"type": "Direct",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
- "contentHash": "ECaTMB4NdV9W1es9J6tN0yoXRPUHKMi5+2L7hcVZ5k9zVdxccIx6+vMllwEYcdTaO0mCETEmdH4F0KxCqgnPaw=="
+ "contentHash": "ECaTMB4NdV9W1es9J6tN0yoXRPUHKMi5+2L7hcVZ5k9zVdxccIx6+vMllwEYcdTaO0mCETEmdH4F0KxCqgnPaw==",
+ "dependencies": {
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0"
+ }
},
"Microsoft.VisualStudio.Azure.Containers.Tools.Targets": {
"type": "Direct",
@@ -53,7 +56,10 @@
"AspNetCore.HealthChecks.UI.Core": {
"type": "Transitive",
"resolved": "9.0.0",
- "contentHash": "TVriy4hgYnhfqz6NAzv8qe62Q8wf82iKUL6WV9selqeFZTq1ILi39Sic6sFQegRysvAVcnxKP/vY8z9Fk8x6XQ=="
+ "contentHash": "TVriy4hgYnhfqz6NAzv8qe62Q8wf82iKUL6WV9selqeFZTq1ILi39Sic6sFQegRysvAVcnxKP/vY8z9Fk8x6XQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Diagnostics.HealthChecks": "8.0.11"
+ }
},
"AspNetCore.HealthChecks.UI.Data": {
"type": "Transitive",
@@ -69,7 +75,8 @@
"resolved": "1.4.0",
"contentHash": "1cnkP90c+zNcRyabjKSA3VYJvpYfkGEpXeekfF8KdTFo3VyUUFOioAsANbG8nsMyedGcmUOqHWd1d3fOXke4VA==",
"dependencies": {
- "NETStandard.Library": "1.6.1"
+ "NETStandard.Library": "1.6.1",
+ "System.Buffers": "4.4.0"
}
},
"Common.Logging": {
@@ -77,13 +84,23 @@
"resolved": "3.4.1",
"contentHash": "5eZ/vgEOqzLg4PypZqnJ+wMhhgHyckicbZY4iDxqQ4FtOz0CpdYZ0xQ78aszMzeAJZiLLb5VdR9tPfunVQLz6g==",
"dependencies": {
- "Common.Logging.Core": "3.4.1"
+ "Common.Logging.Core": "3.4.1",
+ "Microsoft.CSharp": "4.0.1",
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Globalization": "4.0.11",
+ "System.Reflection.TypeExtensions": "4.1.0",
+ "System.Runtime.Extensions": "4.1.0",
+ "System.Threading": "4.0.11"
}
},
"Common.Logging.Core": {
"type": "Transitive",
"resolved": "3.4.1",
- "contentHash": "wLHldZHvxsSD6Ahonfj00/SkfHfKqO+YT6jsUwVm8Rch1REL9IArHAcSLXxYxYfu5/4ydGtmXvOtaH3AkVPu0A=="
+ "contentHash": "wLHldZHvxsSD6Ahonfj00/SkfHfKqO+YT6jsUwVm8Rch1REL9IArHAcSLXxYxYfu5/4ydGtmXvOtaH3AkVPu0A==",
+ "dependencies": {
+ "Microsoft.CSharp": "4.0.1"
+ }
},
"FastEnum.Core": {
"type": "Transitive",
@@ -110,13 +127,17 @@
"resolved": "2.46.6",
"contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
"dependencies": {
- "Grpc.Core.Api": "2.46.6"
+ "Grpc.Core.Api": "2.46.6",
+ "System.Memory": "4.5.3"
}
},
"Grpc.Core.Api": {
"type": "Transitive",
"resolved": "2.46.6",
- "contentHash": "Z7HJGqJYyKb53qfp1jf0wRDYs3sxOnkAFxXAW6q52LLmX/zxzjtFLI9eaWO5UC0weiWjn4iT1FzR+tj9qYZAMg=="
+ "contentHash": "Z7HJGqJYyKb53qfp1jf0wRDYs3sxOnkAFxXAW6q52LLmX/zxzjtFLI9eaWO5UC0weiWjn4iT1FzR+tj9qYZAMg==",
+ "dependencies": {
+ "System.Memory": "4.5.3"
+ }
},
"Humanizer.Core": {
"type": "Transitive",
@@ -165,6 +186,16 @@
"resolved": "5.0.0",
"contentHash": "pg1W2VwaEQMAiTpGK840hZgzavnqjlCMTVSbtVCXVyT+7AX4mc1o89SPv4TBlAjhgCOo9c1Y+jZ5m3ti2YgGgA=="
},
+ "Microsoft.AspNetCore.Cryptography.Internal": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "jGlm8BsWcN1IIxLaxcHP6s0u2OEiBMa0HPCiWkMK7xox/h4WP2CRMyk7tV0cJC5LdM3JoR5UUqU2cxat6ElwlA=="
+ },
+ "Microsoft.AspNetCore.DataProtection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "MFwimSi2FH/CMGydm5EnoQFORoaArEX4QG1nijiRN05XUyJqzWwIlYT4AvnhoU1cGett/EvD416f7OnrDisbiA=="
+ },
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -173,19 +204,29 @@
"Microsoft.ClearScript.Core": {
"type": "Transitive",
"resolved": "7.5.0",
- "contentHash": "7BfzQZA7LdgpfJGSy/GBzKuURb32UpJGQObH5WAavkUxS/u9h/KaEl8N4812F6f4UWVrtwI5XdRgLMu6ukt38A=="
+ "contentHash": "7BfzQZA7LdgpfJGSy/GBzKuURb32UpJGQObH5WAavkUxS/u9h/KaEl8N4812F6f4UWVrtwI5XdRgLMu6ukt38A==",
+ "dependencies": {
+ "Microsoft.Win32.Registry": "5.0.0"
+ }
},
"Microsoft.ClearScript.V8.ICUData": {
"type": "Transitive",
"resolved": "7.5.0",
- "contentHash": "brX7rIjvZPt/ZDSZOPf36ULxhlsFcEgg2WLeOXCFkexTH7MWgUGy//6vMry/QvTLhSgDrs5z+8SbEU1krnuxRg=="
+ "contentHash": "brX7rIjvZPt/ZDSZOPf36ULxhlsFcEgg2WLeOXCFkexTH7MWgUGy//6vMry/QvTLhSgDrs5z+8SbEU1krnuxRg==",
+ "dependencies": {
+ "System.Text.RegularExpressions": "4.3.1"
+ }
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "lwAbIZNdnY0SUNoDmZHkVUwLO8UyNnyyh1t/4XsbFxi4Ounb3xszIYZaWhyj5ZjyfcwqwmtMbE7fUTVCqQEIdQ==",
"dependencies": {
- "Microsoft.CodeAnalysis.Analyzers": "3.3.3"
+ "Microsoft.CodeAnalysis.Analyzers": "3.3.3",
+ "System.Collections.Immutable": "6.0.0",
+ "System.Reflection.Metadata": "6.0.1",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encoding.CodePages": "6.0.0"
}
},
"Microsoft.CodeAnalysis.CSharp.Workspaces": {
@@ -207,7 +248,32 @@
"Humanizer.Core": "2.14.1",
"Microsoft.Bcl.AsyncInterfaces": "6.0.0",
"Microsoft.CodeAnalysis.Common": "[4.5.0]",
- "System.Composition": "6.0.0"
+ "System.Composition": "6.0.0",
+ "System.IO.Pipelines": "6.0.3",
+ "System.Threading.Channels": "6.0.0"
+ }
+ },
+ "Microsoft.CSharp": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==",
+ "dependencies": {
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Dynamic.Runtime": "4.0.11",
+ "System.Globalization": "4.0.11",
+ "System.Linq": "4.1.0",
+ "System.Linq.Expressions": "4.1.0",
+ "System.ObjectModel": "4.0.12",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Extensions": "4.0.1",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Reflection.TypeExtensions": "4.1.0",
+ "System.Resources.ResourceManager": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Extensions": "4.1.0",
+ "System.Runtime.InteropServices": "4.1.0",
+ "System.Threading": "4.0.11"
}
},
"Microsoft.EntityFrameworkCore": {
@@ -216,7 +282,9 @@
"contentHash": "stbjWBTtpQ1HtqXMFyKnXFTr76PvaOHI2b2h85JqBi3eZr00nspvR/a90Zwh8CQ4rVawqLiTG0+0yZQWaav+sQ==",
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "8.0.11",
- "Microsoft.EntityFrameworkCore.Analyzers": "8.0.11"
+ "Microsoft.EntityFrameworkCore.Analyzers": "8.0.11",
+ "Microsoft.Extensions.Caching.Memory": "8.0.1",
+ "Microsoft.Extensions.Logging": "8.0.1"
}
},
"Microsoft.EntityFrameworkCore.Abstractions": {
@@ -254,14 +322,162 @@
"resolved": "8.0.11",
"contentHash": "3TuuW3i5I4Ro0yoaHmi2MqEDGObOVuhLaMEnd/heaLB1fcvm4fu4PevmC4BOWnI0vo176AIlV5o4rEQciLoohw==",
"dependencies": {
- "Microsoft.EntityFrameworkCore": "8.0.11"
+ "Microsoft.EntityFrameworkCore": "8.0.11",
+ "Microsoft.Extensions.Configuration.Abstractions": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.Caching.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Zcoy6H9mSoGyvr7UvlGokEZrlZkcPCICPZr8mCsSt9U/N8eeCwCXwKF5bShdA66R0obxBCwP4AxomQHvVkC/uA==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "YIMO9T3JL8MeEXgVozKt2v79hquo/EFtnY0vgxmLnUvk1Rei/halI7kOWZL2RBeV9FMGzgM9LZA8CVaNwFMaNA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Primitives": "9.0.0"
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "d2kDKnCsJvY7mBVhcjPSp9BkJk48DsaHPg5u+Oy4f8XaOqnEedRy/USyvnpHL92wpJ6DrTPy7htppUUzskbCXQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
}
},
+ "Microsoft.Extensions.Configuration.Binder": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "RiScL99DcyngY9zJA2ROrri7Br8tn5N4hP4YNvGdTN/bvg1A3dwvDOxHnNZ3Im7x2SJ5i4LkX1uPiR/MfSFBLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "L3AdmZ1WOK4XXT5YFPEwyt0ep6l8lGIPs7F5OOBZc77Zqeo01Of7XXICy47628sdVl0v/owxYJTe86DTgFwKCA=="
+ },
"Microsoft.Extensions.DependencyModel": {
"type": "Transitive",
"resolved": "8.0.2",
"contentHash": "mUBDZZRgZrSyFOsJ2qJJ9fXfqd/kXJwf3AiDoqLD9m6TjY5OO/vLNOb9fb4juC0487eq4hcGN/M2Rh/CKS7QYw=="
},
+ "Microsoft.Extensions.Diagnostics": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "3PZp/YSkIXrF7QK7PfC1bkyRYwqOHpWFad8Qx+4wkuumAeXo1NHaxpS9LboNA9OvNSAu+QOVlXbMyoY+pHSqcw==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "8.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "SfK89ytD61S7DgzorFljSkUeluC1ncn6dtZgwc0ot39f/BEYWBl5jpgvodxduoYAs1d9HG8faCDRZxE95UMo2A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.HealthChecks": {
+ "type": "Transitive",
+ "resolved": "8.0.11",
+ "contentHash": "zLgN22Zp9pk8RHlwssRTexw4+a6wqOnKWN+VejdPn5Yhjql4XiBhkFo35Nu8mmqHIk/UEmmCnMGLWq75aFfkOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "8.0.11",
+ "Microsoft.Extensions.Hosting.Abstractions": "8.0.1",
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.2",
+ "Microsoft.Extensions.Options": "8.0.2"
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": {
+ "type": "Transitive",
+ "resolved": "8.0.11",
+ "contentHash": "So3JUdRxozRjvQ3cxU6F3nI/i4emDnjane6yMYcJhvTTTu29ltlIdoXjkFGRceIWz8yKvuEpzXItZ0x5GvN2nQ=="
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "/ppSdehKk3fuXjlqCDgSOtjRK/pSHU8eWgzSHfHdwVm5BP4Dgejehkw+PtxKG2j98qTDEHDst2Y99aNsmJldmw==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Hosting.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "KrN6TGFwCwqOkLLk/idW/XtDQh+8In+CL9T4M1Dx+5ScsjTq4TlVbal8q532m82UYrMr6RiQJF2HvYCN0QwVsA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0",
+ "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Http": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "cWz4caHwvx0emoYe7NkHPxII/KkTI8R/LC9qdqJqnKv2poTJ4e2qqPGQqvRoQ5kaSA4FU5IV3qFAuLuOhoqULQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "8.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
+ "Microsoft.Extensions.Diagnostics": "8.0.0",
+ "Microsoft.Extensions.Logging": "8.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.0",
+ "Microsoft.Extensions.Options": "8.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Configuration": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "H05HiqaNmg6GjH34ocYE9Wm1twm3Oz2aXZko8GTwGBzM7op2brpAA8pJ5yyD1OpS1mXUtModBYOlcZ/wXeWsSg==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.0",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Configuration.Binder": "9.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Logging": "9.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Options": "9.0.0",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "8oCAgXOow5XDrY9HaXX1QmH3ORsyZO/ANVHBlhLyCeWTH5Sg4UuqZeOTWJi6484M+LqSx0RqQXDJtdYy2BNiLQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Options.ConfigurationExtensions": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "Ob3FXsXkcSMQmGZi7qP07EQ39kZpSBlTcAZLbJLdI4FIf0Jug8biv2HTavWmnTirchctPlq9bl/26CXtQRguzA==",
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Configuration.Binder": "9.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Options": "9.0.0",
+ "Microsoft.Extensions.Primitives": "9.0.0"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "inRnbpCS0nwO/RuoZIAqxQUuyjaknOOnCEZB55KSMMjRhl0RQDttSmLSGsUJN3RQ3ocf5NDLFd2mOQViHqMK5w=="
+ },
"Microsoft.IdentityModel.Abstractions": {
"type": "Transitive",
"resolved": "8.15.0",
@@ -280,13 +496,28 @@
"resolved": "8.15.0",
"contentHash": "zUE9ysJXBtXlHHRtcRK3Sp8NzdCI1z/BRDTXJQ2TvBoI0ENRtnufYIep0O5TSCJRJGDwwuLTUx+l/bEYZUxpCA==",
"dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
"Microsoft.IdentityModel.Logging": "8.15.0"
}
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
- "resolved": "1.1.0",
- "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
+ "resolved": "5.0.0",
+ "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ=="
+ },
+ "Microsoft.NETCore.Targets": {
+ "type": "Transitive",
+ "resolved": "1.1.3",
+ "contentHash": "3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ=="
+ },
+ "Microsoft.Win32.Registry": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
+ "dependencies": {
+ "System.Security.AccessControl": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
},
"Mono.TextTemplating": {
"type": "Transitive",
@@ -330,13 +561,18 @@
"dependencies": {
"Nethermind.DotNetty.Buffers": "1.0.2.76",
"Nethermind.DotNetty.Common": "1.0.2.76",
- "Nethermind.DotNetty.Transport": "1.0.2.76"
+ "Nethermind.DotNetty.Transport": "1.0.2.76",
+ "System.Collections.Immutable": "1.5.0"
}
},
"Nethermind.DotNetty.Common": {
"type": "Transitive",
"resolved": "1.0.2.76",
- "contentHash": "rraxAOK8Pww3ReW2NkCCr/pwXTp88gI4lXaeA5TriPnp1wZg8jJdZYIj2m2+HKkVtw1C1F1sRA7FzfgBodA3Tw=="
+ "contentHash": "rraxAOK8Pww3ReW2NkCCr/pwXTp88gI4lXaeA5TriPnp1wZg8jJdZYIj2m2+HKkVtw1C1F1sRA7FzfgBodA3Tw==",
+ "dependencies": {
+ "Microsoft.Extensions.Logging": "5.0.0",
+ "System.Runtime.CompilerServices.Unsafe": "5.0.0"
+ }
},
"Nethermind.Libp2p.Core": {
"type": "Transitive",
@@ -345,6 +581,9 @@
"dependencies": {
"BouncyCastle.Cryptography": "2.4.0",
"Google.Protobuf": "3.28.3",
+ "Microsoft.Extensions.DependencyInjection": "9.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Multiformats.Address": "1.1.8",
"SimpleBase": "4.0.2"
}
@@ -355,6 +594,7 @@
"contentHash": "8hEzwS9eYYy1xvmXq+6VcfKcOflEmnPdT5UA8Lhr0cdK2af+wV6tMwHhuvqF0L7N+bdaFMNcUUhBhy17jafutw==",
"dependencies": {
"Google.Protobuf": "3.28.3",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45",
"Nethermind.Libp2p.Protocols.IpTcp": "1.0.0-preview.45"
}
@@ -364,6 +604,7 @@
"resolved": "1.0.0-preview.45",
"contentHash": "vDoUfrz/45OEKc9TMEs9l0wPWW4r49opS/J+bh3zUTMLaWWf9jl8zkbPh5mz9moBh1JdDVuLRSPT3zRd8/Gvkg==",
"dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45"
}
},
@@ -373,6 +614,7 @@
"contentHash": "NZhHziBoq9mGeqV8o0QMoKOnBLjyPEIhEIcsnL6rdV4nJ1PwRWort8O811dh4aWq8rxVm1dkj66U4Q/ZwEX+JQ==",
"dependencies": {
"Makaretu.Dns.Multicast": "0.27.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45"
}
},
@@ -430,6 +672,7 @@
"contentHash": "TfdjpazHxi/Pxfa8oR3wPDoWzgTJJ9L0OHQo5hkozte9mpa8sUim+cfIiEC9qtAjq4D1/MfpvfQaZZzeRh2akQ==",
"dependencies": {
"BouncyCastle.Cryptography": "2.4.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45"
}
},
@@ -447,6 +690,7 @@
"resolved": "1.0.0-preview.45",
"contentHash": "BJXIfz9T1zPRJjVHGn4qJLvZu2vKnjoSoT9Zd+nYePc+C4ESwhtFuuHHSirnuKqJ/GVY2v8lvhb+fnjYSV3E8w==",
"dependencies": {
+ "Microsoft.Extensions.Logging": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45",
"Nethermind.Libp2p.Protocols.Quic": "1.0.0-preview.45"
}
@@ -456,6 +700,7 @@
"resolved": "1.0.0-preview.45",
"contentHash": "ElNnTVoTxpHZMGTFbKTndQ1C3jFMMVLQfK1wzJVAw5sD294Yur42UKxdHtrzQJEJ/XHARz5ORxwtWcbprCQLDA==",
"dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45"
}
},
@@ -505,6 +750,9 @@
"contentHash": "fYnHQ8yZcj9W0fPGbzMkZUnE14aGGTFS8WE0Ow2hXiGhJ61Tv71cTi1yuugHxPCLyb87JpWMkq4lix8Rf06vtA==",
"dependencies": {
"NETStandard.Library": "1.6.1",
+ "System.Buffers": "4.5.0",
+ "System.Memory": "4.5.0",
+ "System.ValueTuple": "4.4.0",
"libsodium": "1.0.16"
}
},
@@ -535,21 +783,42 @@
"resolved": "1.8.5",
"contentHash": "EaCgmntbH1sOzemRTqyXSqYjB6pLH7VCYHhhDYZ59guHSD5qPwhIYa7kfy0QUlmTRt9IXhaXdFhNuBUArp70Ng=="
},
- "prometheus-net": {
- "type": "Transitive",
- "resolved": "8.2.1",
- "contentHash": "3wVgdEPOCBF752s2xps5T+VH+c9mJK8S8GKEDg49084P6JZMumTZI5Te6aJ9MQpX0sx7om6JOnBpIi7ZBmmiDQ=="
- },
"SimpleBase": {
"type": "Transitive",
"resolved": "4.0.2",
- "contentHash": "sNKHP2Qzy4DafamgH44UGg1YeyHFT08AMgHPraxYt4CVBoHHYD5f0MjbBfdmtGca69xikPU5aV8H+MMP7ZnfIg=="
+ "contentHash": "sNKHP2Qzy4DafamgH44UGg1YeyHFT08AMgHPraxYt4CVBoHHYD5f0MjbBfdmtGca69xikPU5aV8H+MMP7ZnfIg==",
+ "dependencies": {
+ "System.Memory": "4.5.5"
+ }
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "pL2ChpaRRWI/p4LXyy4RgeWlYF2sgfj/pnVMvBqwNFr5cXg7CXNnWZWxrOONLg8VGdFB8oB+EG2Qw4MLgTOe+A=="
},
"System.CodeDom": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "2sCCb7doXEwtYAbqzbF/8UAeDRMNmPaQbU2q50Psg1J9KzumyVVCgKQY8s53WIPTufNT0DpSe9QRvVjOzfDWBA=="
},
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
+ }
+ },
+ "System.Collections.Immutable": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
"System.Composition": {
"type": "Transitive",
"resolved": "6.0.0",
@@ -598,257 +867,608 @@
"System.Composition.Runtime": "6.0.0"
}
},
- "System.Reactive": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "31kfaW4ZupZzPsI5PVe77VhnvFF55qgma7KZr/E0iFTs6fmdhhG8j0mgEx620iLTey1EynOkEfnyTjtNEpJzGw=="
- },
- "Testably.Abstractions.FileSystem.Interface": {
+ "System.Diagnostics.Debug": {
"type": "Transitive",
- "resolved": "9.0.0",
- "contentHash": "uksk86YlnzAdyfVNu3wICU0X5iXVe9LF7Q3UkngNliHWEvM5gvAlOUr+jmd9JwmbJWISH5+i1vyXE02lEVz7WQ=="
+ "resolved": "4.0.11",
+ "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
+ }
},
- "Tmds.LibC": {
+ "System.Diagnostics.EventLog": {
"type": "Transitive",
- "resolved": "0.2.0",
- "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
},
- "YamlDotNet": {
+ "System.Dynamic.Runtime": {
"type": "Transitive",
- "resolved": "16.3.0",
- "contentHash": "SgMOdxbz8X65z8hraIs6hOEdnkH6hESTAIUa7viEngHOYaH+6q5XJmwr1+yb9vJpNQ19hCQY69xbFsLtXpobQA=="
- },
- "nethermind.abi": {
- "type": "Project",
+ "resolved": "4.0.11",
+ "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==",
"dependencies": {
- "MathNet.Numerics.FSharp": "[5.0.0, )",
- "Nethermind.Core": "[1.36.0-unstable, )"
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Globalization": "4.0.11",
+ "System.Linq": "4.1.0",
+ "System.Linq.Expressions": "4.1.0",
+ "System.ObjectModel": "4.0.12",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Emit": "4.0.1",
+ "System.Reflection.Emit.ILGeneration": "4.0.1",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Reflection.TypeExtensions": "4.1.0",
+ "System.Resources.ResourceManager": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Extensions": "4.1.0",
+ "System.Threading": "4.0.11"
}
},
- "nethermind.api": {
- "type": "Project",
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
"dependencies": {
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Facade": "[1.36.0-unstable, )",
- "Nethermind.Grpc": "[1.36.0-unstable, )",
- "Nethermind.History": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )",
- "Nethermind.Monitoring": "[1.36.0-unstable, )",
- "Nethermind.Network": "[1.36.0-unstable, )",
- "Nethermind.Sockets": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.blockchain": {
- "type": "Project",
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
"dependencies": {
- "Microsoft.ClearScript.V8.Native.linux-arm64": "[7.5.0, )",
- "Microsoft.ClearScript.V8.Native.linux-x64": "[7.5.0, )",
- "Microsoft.ClearScript.V8.Native.osx-arm64": "[7.5.0, )",
- "Microsoft.ClearScript.V8.Native.osx-x64": "[7.5.0, )",
- "Microsoft.ClearScript.V8.Native.win-x64": "[7.5.0, )",
- "Nethermind.Abi": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Db": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.Evm.Precompiles": "[1.36.0-unstable, )",
- "Nethermind.Network.Stats": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )",
- "Nethermind.State": "[1.36.0-unstable, )",
- "Nethermind.TxPool": "[1.36.0-unstable, )",
- "Polly": "[8.6.4, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Threading.Tasks": "4.0.11"
}
},
- "nethermind.config": {
- "type": "Project",
+ "System.IO.Pipelines": {
+ "type": "Transitive",
+ "resolved": "6.0.3",
+ "contentHash": "ryTgF+iFkpGZY1vRQhfCzX0xTdlV3pyaTTqRu2ETbEv+HlV7O6y7hyQURnghNIXvctl5DuZ//Dpks6HdL/Txgw=="
+ },
+ "System.Linq": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "bQ0iYFOQI0nuTnt+NQADns6ucV4DUvMdwN6CbkB1yj8i7arTGiTN5eok1kQwdnnNWSDZfIUySQY+J3d5KjWn0g==",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "NonBlocking": "[2.1.2, )",
- "System.Configuration.ConfigurationManager": "[10.0.0, )"
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Resources.ResourceManager": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Extensions": "4.1.0"
}
},
- "nethermind.consensus": {
- "type": "Project",
+ "System.Linq.Expressions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "I+y02iqkgmCAyfbqOmSDOgqdZQ5tTj80Akm5BPSS8EeB0VGWdy6X1KCoYe8Pk6pwDoAKZUOdLVxnTJcExiv5zw==",
"dependencies": {
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.TxPool": "[1.36.0-unstable, )"
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Globalization": "4.0.11",
+ "System.IO": "4.1.0",
+ "System.Linq": "4.1.0",
+ "System.ObjectModel": "4.0.12",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Emit": "4.0.1",
+ "System.Reflection.Emit.ILGeneration": "4.0.1",
+ "System.Reflection.Emit.Lightweight": "4.0.1",
+ "System.Reflection.Extensions": "4.0.1",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Reflection.TypeExtensions": "4.1.0",
+ "System.Resources.ResourceManager": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Extensions": "4.1.0",
+ "System.Threading": "4.0.11"
}
},
- "nethermind.consensus.aura": {
- "type": "Project",
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.5",
+ "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw=="
+ },
+ "System.ObjectModel": {
+ "type": "Transitive",
+ "resolved": "4.0.12",
+ "contentHash": "tAgJM1xt3ytyMoW4qn4wIqgJYm7L7TShRZG4+Q4Qsi2PCcj96pXN7nRywS9KkB3p/xDUjc2HSwP9SROyPYDYKQ==",
"dependencies": {
- "BouncyCastle.Cryptography": "[2.6.2, )",
- "Nethermind.Abi": "[1.36.0-unstable, )",
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Facade": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )",
- "Nethermind.Synchronization": "[1.36.0-unstable, )",
- "Nito.Collections.Deque": "[1.2.1, )"
+ "System.Collections": "4.0.11",
+ "System.Diagnostics.Debug": "4.0.11",
+ "System.Resources.ResourceManager": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Threading": "4.0.11"
}
},
- "nethermind.consensus.clique": {
- "type": "Project",
+ "System.Reactive": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "31kfaW4ZupZzPsI5PVe77VhnvFF55qgma7KZr/E0iFTs6fmdhhG8j0mgEx620iLTey1EynOkEfnyTjtNEpJzGw=="
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.IO": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.consensus.ethash": {
- "type": "Project",
+ "System.Reflection.Emit": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "P2wqAj72fFjpP6wb9nSfDqNBMab+2ovzSDzUZK7MVIm54tBJEPr9jWfSjjoTpPwj1LeKcmX3vr0ttyjSSFM47g==",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )"
+ "System.IO": "4.1.0",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Emit.ILGeneration": "4.0.1",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.core": {
- "type": "Project",
+ "System.Reflection.Emit.ILGeneration": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "Ov6dU8Bu15Bc7zuqttgHF12J5lwSWyTf1S+FJouUXVMSqImLZzYaQ+vRr1rQ0OZ0HqsrwWl4dsKHELckQkVpgA==",
"dependencies": {
- "Autofac": "[9.0.0, )",
- "Autofac.Extensions.DependencyInjection": "[10.0.0, )",
- "FastEnum": "[2.0.6, )",
- "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
- "Microsoft.IdentityModel.JsonWebTokens": "[8.15.0, )",
- "Nethermind.Crypto.SecP256k1": "[1.5.0, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
- "Nethermind.Numerics.Int256": "[1.3.6, )",
- "NonBlocking": "[2.1.2, )",
- "TestableIO.System.IO.Abstractions.Wrappers": "[22.0.16, )"
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.crypto": {
- "type": "Project",
+ "System.Reflection.Emit.Lightweight": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "sSzHHXueZ5Uh0OLpUQprhr+ZYJrLPA2Cmr4gn0wj9+FftNKXx8RIMKvO9qnjk2ebPYUjZ+F2ulGdPOsvj+MEjA==",
"dependencies": {
- "BouncyCastle.Cryptography": "[2.6.2, )",
- "Ckzg.Bindings": "[2.1.5.1542, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto.Bls": "[1.0.5, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "System.Security.Cryptography.ProtectedData": "[10.0.0, )"
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Emit.ILGeneration": "4.0.1",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.db": {
- "type": "Project",
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "NonBlocking": "[2.1.2, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.db.rocks": {
- "type": "Project",
+ "System.Reflection.Metadata": {
+ "type": "Transitive",
+ "resolved": "6.0.1",
+ "contentHash": "III/lNMSn0ZRBuM9m5Cgbiho5j81u0FAEagFX5ta2DKbljZ3T0IpD8j+BIiHQPeKqJppWS9bGEp6JnKnWKze0g==",
"dependencies": {
- "ConcurrentHashSet": "[1.3.0, )",
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Db": "[1.36.0-unstable, )",
- "NonBlocking": "[2.1.2, )",
- "RocksDB": "[10.4.2.62659, 10.4.2.62659]"
+ "System.Collections.Immutable": "6.0.0"
}
},
- "nethermind.db.rpc": {
- "type": "Project",
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
"dependencies": {
- "Nethermind.Db": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Json": "[1.36.0-unstable, )",
- "Nethermind.State": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.era1": {
- "type": "Project",
+ "System.Reflection.TypeExtensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "tsQ/ptQ3H5FYfON8lL4MxRk/8kFyE0A+tGPXmVP967cT/gzLHYxIejIYSxp4JmIeFHVP78g/F2FE1mUUTbDtrg==",
"dependencies": {
- "CommunityToolkit.HighPerformance": "[8.4.0, )",
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )",
- "Nethermind.Merkleization": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Ssz": "[1.36.0-unstable, )",
- "Nethermind.State": "[1.36.0-unstable, )",
- "Snappier": "[1.2.0, )"
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.ethstats": {
- "type": "Project",
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
- "Nethermind.Network": "[1.36.0-unstable, )",
- "Websocket.Client": "[5.3.0, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Globalization": "4.0.11",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.evm": {
- "type": "Project",
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "Microsoft.NETCore.Targets": "1.1.3"
}
},
- "nethermind.evm.precompiles": {
- "type": "Project",
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Crypto.Bls": "[1.0.5, )",
- "Nethermind.Crypto.SecP256r1": "[1.0.0-preview.6, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.GmpBindings": "[1.0.3, )",
- "Nethermind.MclBindings": "[1.0.3, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.externalsigner.plugin": {
- "type": "Project",
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
}
},
- "nethermind.facade": {
- "type": "Project",
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
"dependencies": {
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Synchronization": "[1.36.0-unstable, )",
- "NonBlocking": "[2.1.2, )"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Handles": "4.0.1"
}
},
- "nethermind.flashbots": {
- "type": "Project",
+ "System.Security.AccessControl": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
"dependencies": {
- "Nethermind.Merge.Plugin": "[1.36.0-unstable, )"
+ "Microsoft.NETCore.Platforms": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
}
},
- "nethermind.grpc": {
- "type": "Project",
- "dependencies": {
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UPWqLSygJlFerRi9XNIuM0a1VC8gHUIufyP24xQ0sc+XimqUAEcjpOz9DhKpyDjH+5B/wO3RpC0KpkEeDj/ddg=="
+ },
+ "System.Security.Cryptography.Xml": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "Vb1vrLKtg0icvKk0GCzCErclNRH6NB7TMZ9BgXH9xqQ0lFlByQeoVwbewteJDuOPh1774GuVLD7rQrxhrpCCuA==",
+ "dependencies": {
+ "System.Security.Cryptography.Pkcs": "10.0.0"
+ }
+ },
+ "System.Security.Principal.Windows": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
+ }
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Text.RegularExpressions": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "N0kNRrWe4+nXOWlpLT4LAY5brb8caNFlUuIRpraCVMDLYutKkol1aV079rQjLuSxKMJT2SpBQsYX9xbcTMmzwg==",
+ "dependencies": {
+ "System.Runtime": "4.3.1"
+ }
+ },
+ "System.Threading": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "N+3xqIcg3VDKyjwwCGaZ9HawG9aC6cSDI+s7ROma310GQo8vilFZa86hqKppwTHleR/G0sfOzhvgnUxWCR/DrQ==",
+ "dependencies": {
+ "System.Runtime": "4.1.0",
+ "System.Threading.Tasks": "4.0.11"
+ }
+ },
+ "System.Threading.Channels": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "TY8/9+tI0mNaUMgntOxxaq2ndTkdXqLSxvPmas7XEqOlv9lQtB7wLjYGd756lOaO7Dvb5r/WXhluM+0Xe87v5Q=="
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0"
+ }
+ },
+ "System.Threading.Tasks.Dataflow": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "7V0I8tPa9V7UxMx/+7DIwkhls5ouaEMQx6l/GwGm1Y8kJQ61On9B/PxCXFLbgu5/C47g0BP2CUYs+nMv1+Oaqw=="
+ },
+ "System.ValueTuple": {
+ "type": "Transitive",
+ "resolved": "4.4.0",
+ "contentHash": "BahUww/+mdP4ARCAh2RQhQTg13wYLVrBb9SYVgW8ZlrwjraGCXHGjo0oIiUfZ34LUZkMMR+RAzR7dEY4S1HeQQ=="
+ },
+ "Testably.Abstractions.FileSystem.Interface": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "uksk86YlnzAdyfVNu3wICU0X5iXVe9LF7Q3UkngNliHWEvM5gvAlOUr+jmd9JwmbJWISH5+i1vyXE02lEVz7WQ=="
+ },
+ "Tmds.LibC": {
+ "type": "Transitive",
+ "resolved": "0.2.0",
+ "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ },
+ "YamlDotNet": {
+ "type": "Transitive",
+ "resolved": "16.3.0",
+ "contentHash": "SgMOdxbz8X65z8hraIs6hOEdnkH6hESTAIUa7viEngHOYaH+6q5XJmwr1+yb9vJpNQ19hCQY69xbFsLtXpobQA=="
+ },
+ "nethermind.abi": {
+ "type": "Project",
+ "dependencies": {
+ "MathNet.Numerics.FSharp": "[5.0.0, )",
+ "Nethermind.Core": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.api": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Facade": "[1.37.0-unstable, )",
+ "Nethermind.Grpc": "[1.37.0-unstable, )",
+ "Nethermind.History": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )",
+ "Nethermind.Monitoring": "[1.37.0-unstable, )",
+ "Nethermind.Network": "[1.37.0-unstable, )",
+ "Nethermind.Sockets": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.blockchain": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.ClearScript.V8.Native.linux-arm64": "[7.5.0, )",
+ "Microsoft.ClearScript.V8.Native.linux-x64": "[7.5.0, )",
+ "Microsoft.ClearScript.V8.Native.osx-arm64": "[7.5.0, )",
+ "Microsoft.ClearScript.V8.Native.osx-x64": "[7.5.0, )",
+ "Microsoft.ClearScript.V8.Native.win-x64": "[7.5.0, )",
+ "Nethermind.Abi": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.Evm.Precompiles": "[1.37.0-unstable, )",
+ "Nethermind.Network.Stats": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )",
+ "Nethermind.State": "[1.37.0-unstable, )",
+ "Nethermind.TxPool": "[1.37.0-unstable, )",
+ "Polly": "[8.6.4, )"
+ }
+ },
+ "nethermind.config": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "NonBlocking": "[2.1.2, )",
+ "System.Configuration.ConfigurationManager": "[10.0.0, )"
+ }
+ },
+ "nethermind.consensus": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.TxPool": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.consensus.aura": {
+ "type": "Project",
+ "dependencies": {
+ "BouncyCastle.Cryptography": "[2.6.2, )",
+ "Nethermind.Abi": "[1.37.0-unstable, )",
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Facade": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )",
+ "Nethermind.Synchronization": "[1.37.0-unstable, )",
+ "Nito.Collections.Deque": "[1.2.1, )"
+ }
+ },
+ "nethermind.consensus.clique": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.consensus.ethash": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.core": {
+ "type": "Project",
+ "dependencies": {
+ "Autofac": "[9.0.0, )",
+ "Autofac.Extensions.DependencyInjection": "[10.0.0, )",
+ "FastEnum": "[2.0.6, )",
+ "Microsoft.Extensions.DependencyInjection": "[10.0.0, )",
+ "Microsoft.Extensions.ObjectPool": "[10.0.0, )",
+ "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
+ "Microsoft.IdentityModel.JsonWebTokens": "[8.15.0, )",
+ "Nethermind.Crypto.SecP256k1": "[1.5.0, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
+ "Nethermind.Numerics.Int256": "[1.3.6, )",
+ "NonBlocking": "[2.1.2, )",
+ "TestableIO.System.IO.Abstractions.Wrappers": "[22.0.16, )",
+ "prometheus-net": "[8.2.1, )"
+ }
+ },
+ "nethermind.crypto": {
+ "type": "Project",
+ "dependencies": {
+ "BouncyCastle.Cryptography": "[2.6.2, )",
+ "Ckzg.Bindings": "[2.1.5.1542, )",
+ "Microsoft.AspNetCore.DataProtection": "[10.0.0, )",
+ "Microsoft.AspNetCore.DataProtection.Extensions": "[10.0.0, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto.Bls": "[1.0.5, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "System.Security.Cryptography.ProtectedData": "[10.0.0, )"
+ }
+ },
+ "nethermind.db": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "NonBlocking": "[2.1.2, )"
+ }
+ },
+ "nethermind.db.rocks": {
+ "type": "Project",
+ "dependencies": {
+ "ConcurrentHashSet": "[1.3.0, )",
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "NonBlocking": "[2.1.2, )",
+ "RocksDB": "[10.4.2.62659, 10.4.2.62659]"
+ }
+ },
+ "nethermind.db.rpc": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Json": "[1.37.0-unstable, )",
+ "Nethermind.State": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.era1": {
+ "type": "Project",
+ "dependencies": {
+ "CommunityToolkit.HighPerformance": "[8.4.0, )",
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )",
+ "Nethermind.Merkleization": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Ssz": "[1.37.0-unstable, )",
+ "Nethermind.State": "[1.37.0-unstable, )",
+ "Snappier": "[1.2.0, )"
+ }
+ },
+ "nethermind.ethstats": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
+ "Nethermind.Network": "[1.37.0-unstable, )",
+ "Websocket.Client": "[5.3.0, )"
+ }
+ },
+ "nethermind.evm": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.evm.precompiles": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Crypto.Bls": "[1.0.5, )",
+ "Nethermind.Crypto.SecP256r1": "[1.0.0-preview.6, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.GmpBindings": "[1.0.3, )",
+ "Nethermind.MclBindings": "[1.0.3, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.externalsigner.plugin": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.facade": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Synchronization": "[1.37.0-unstable, )",
+ "NonBlocking": "[2.1.2, )"
+ }
+ },
+ "nethermind.flashbots": {
+ "type": "Project",
+ "dependencies": {
+ "Nethermind.Merge.Plugin": "[1.37.0-unstable, )"
+ }
+ },
+ "nethermind.grpc": {
+ "type": "Project",
+ "dependencies": {
"Google.Protobuf": "[3.33.1, )",
"Google.Protobuf.Tools": "[3.33.1, )",
"Grpc": "[2.46.6, )",
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Json": "[1.36.0-unstable, )"
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Json": "[1.37.0-unstable, )"
}
},
"nethermind.healthchecks": {
@@ -857,74 +1477,74 @@
"AspNetCore.HealthChecks.UI": "[9.0.0, )",
"AspNetCore.HealthChecks.UI.InMemory.Storage": "[9.0.0, )",
"KubernetesClient": "[18.0.5, )",
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Merge.Plugin": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Merge.Plugin": "[1.37.0-unstable, )"
}
},
"nethermind.history": {
"type": "Project",
"dependencies": {
- "Nethermind.Consensus": "[1.36.0-unstable, )"
+ "Nethermind.Consensus": "[1.37.0-unstable, )"
}
},
"nethermind.hive": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )"
}
},
"nethermind.init": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Db.Rocks": "[1.36.0-unstable, )",
- "Nethermind.Db.Rpc": "[1.36.0-unstable, )",
- "Nethermind.Era1": "[1.36.0-unstable, )",
- "Nethermind.Network.Discovery": "[1.36.0-unstable, )",
- "Nethermind.Network.Dns": "[1.36.0-unstable, )",
- "Nethermind.Network.Enr": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Db.Rocks": "[1.37.0-unstable, )",
+ "Nethermind.Db.Rpc": "[1.37.0-unstable, )",
+ "Nethermind.Era1": "[1.37.0-unstable, )",
+ "Nethermind.Network.Discovery": "[1.37.0-unstable, )",
+ "Nethermind.Network.Dns": "[1.37.0-unstable, )",
+ "Nethermind.Network.Enr": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )"
}
},
"nethermind.init.snapshot": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )"
}
},
"nethermind.jsonrpc": {
"type": "Project",
"dependencies": {
- "Nethermind.Abi": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.Facade": "[1.36.0-unstable, )",
- "Nethermind.Network.Dns": "[1.36.0-unstable, )",
- "Nethermind.Sockets": "[1.36.0-unstable, )",
- "Nethermind.Synchronization": "[1.36.0-unstable, )",
- "Nethermind.Wallet": "[1.36.0-unstable, )"
+ "Nethermind.Abi": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.Facade": "[1.37.0-unstable, )",
+ "Nethermind.Network.Dns": "[1.37.0-unstable, )",
+ "Nethermind.Sockets": "[1.37.0-unstable, )",
+ "Nethermind.Synchronization": "[1.37.0-unstable, )",
+ "Nethermind.Wallet": "[1.37.0-unstable, )"
}
},
"nethermind.jsonrpc.tracestore": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )"
}
},
"nethermind.keystore": {
"type": "Project",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Json": "[1.36.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Json": "[1.37.0-unstable, )",
"SCrypt": "[2.0.0.2, )"
}
},
@@ -935,41 +1555,41 @@
"type": "Project",
"dependencies": {
"NLog": "[5.5.1, )",
- "Nethermind.Logging": "[1.36.0-unstable, )"
+ "Nethermind.Logging": "[1.37.0-unstable, )"
}
},
"nethermind.merge.aura": {
"type": "Project",
"dependencies": {
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Consensus.AuRa": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Db": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.Merge.Plugin": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )",
- "Nethermind.State": "[1.36.0-unstable, )"
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Consensus.AuRa": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.Merge.Plugin": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )",
+ "Nethermind.State": "[1.37.0-unstable, )"
}
},
"nethermind.merge.plugin": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )"
}
},
"nethermind.merkleization": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Ssz": "[1.36.0-unstable, )"
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Ssz": "[1.37.0-unstable, )"
}
},
"nethermind.monitoring": {
"type": "Project",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
"prometheus-net.AspNetCore": "[8.2.1, )"
}
},
@@ -977,31 +1597,32 @@
"type": "Project",
"dependencies": {
"Crc32.NET": "[1.2.0, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
"Nethermind.DotNetty.Handlers": "[1.0.2.76, )",
- "Nethermind.Network.Contract": "[1.36.0-unstable, )",
- "Nethermind.Network.Stats": "[1.36.0-unstable, )",
- "Nethermind.Synchronization": "[1.36.0-unstable, )",
+ "Nethermind.Network.Contract": "[1.37.0-unstable, )",
+ "Nethermind.Network.Stats": "[1.37.0-unstable, )",
+ "Nethermind.Synchronization": "[1.37.0-unstable, )",
"Snappier": "[1.2.0, )"
}
},
"nethermind.network.contract": {
"type": "Project",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )"
+ "Nethermind.Config": "[1.37.0-unstable, )"
}
},
"nethermind.network.discovery": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Facade": "[1.36.0-unstable, )",
- "Nethermind.Network": "[1.36.0-unstable, )",
- "Nethermind.Network.Enr": "[1.36.0-unstable, )",
+ "Microsoft.Extensions.Caching.Memory": "[10.0.0, )",
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Facade": "[1.37.0-unstable, )",
+ "Nethermind.Network": "[1.37.0-unstable, )",
+ "Nethermind.Network.Enr": "[1.37.0-unstable, )",
"PierTwo.Lantern.Discv5.WireProtocol": "[1.0.0-preview.6, )"
}
},
@@ -1009,147 +1630,149 @@
"type": "Project",
"dependencies": {
"DnsClient": "[1.8.0, )",
- "Nethermind.Network": "[1.36.0-unstable, )",
- "Nethermind.Network.Enr": "[1.36.0-unstable, )"
+ "Nethermind.Network": "[1.37.0-unstable, )",
+ "Nethermind.Network.Enr": "[1.37.0-unstable, )"
}
},
"nethermind.network.enr": {
"type": "Project",
"dependencies": {
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Network": "[1.36.0-unstable, )"
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Network": "[1.37.0-unstable, )"
}
},
"nethermind.network.stats": {
"type": "Project",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
- "Nethermind.Network.Contract": "[1.36.0-unstable, )"
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
+ "Nethermind.Network.Contract": "[1.37.0-unstable, )"
}
},
"nethermind.optimism": {
"type": "Project",
"dependencies": {
"Google.Protobuf": "[3.33.1, )",
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )",
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )",
"Nethermind.Libp2p": "[1.0.0-preview.45, )",
"Nethermind.Libp2p.Protocols.PubsubPeerDiscovery": "[1.0.0-preview.45, )",
- "Nethermind.Merge.Plugin": "[1.36.0-unstable, )",
+ "Nethermind.Merge.Plugin": "[1.37.0-unstable, )",
"Snappier": "[1.2.0, )"
}
},
"nethermind.seq": {
"type": "Project",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )"
+ "Nethermind.Config": "[1.37.0-unstable, )"
}
},
"nethermind.serialization.json": {
"type": "Project",
"dependencies": {
"Microsoft.ClearScript.V8": "[7.5.0, )",
- "Nethermind.Core": "[1.36.0-unstable, )"
+ "Nethermind.Core": "[1.37.0-unstable, )"
}
},
"nethermind.serialization.rlp": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
"Nethermind.DotNetty.Buffers": "[1.0.2.76, )"
}
},
"nethermind.serialization.ssz": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )"
+ "Nethermind.Core": "[1.37.0-unstable, )"
}
},
"nethermind.shutter": {
"type": "Project",
"dependencies": {
"Google.Protobuf": "[3.33.1, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )",
"Nethermind.Libp2p": "[1.0.0-preview.45, )",
"Nethermind.Libp2p.Protocols.PubsubPeerDiscovery": "[1.0.0-preview.45, )",
- "Nethermind.Merge.Plugin": "[1.36.0-unstable, )",
- "Nethermind.Merkleization": "[1.36.0-unstable, )",
- "Nethermind.Network.Discovery": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Ssz": "[1.36.0-unstable, )",
- "Nethermind.Specs": "[1.36.0-unstable, )"
+ "Nethermind.Merge.Plugin": "[1.37.0-unstable, )",
+ "Nethermind.Merkleization": "[1.37.0-unstable, )",
+ "Nethermind.Network.Discovery": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Ssz": "[1.37.0-unstable, )",
+ "Nethermind.Specs": "[1.37.0-unstable, )"
}
},
"nethermind.sockets": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Json": "[1.36.0-unstable, )"
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Json": "[1.37.0-unstable, )"
}
},
"nethermind.specs": {
"type": "Project",
"dependencies": {
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Json": "[1.36.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Json": "[1.37.0-unstable, )",
"ZstdSharp.Port": "[0.8.6, )"
}
},
"nethermind.state": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Db": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "Nethermind.Trie": "[1.36.0-unstable, )"
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "Nethermind.Trie": "[1.37.0-unstable, )",
+ "ZstdSharp.Port": "[0.8.6, )",
+ "prometheus-net": "[8.2.1, )"
}
},
"nethermind.synchronization": {
"type": "Project",
"dependencies": {
"ConcurrentHashSet": "[1.3.0, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.History": "[1.36.0-unstable, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
- "Nethermind.Network.Contract": "[1.36.0-unstable, )",
- "Nethermind.Trie": "[1.36.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.History": "[1.37.0-unstable, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
+ "Nethermind.Network.Contract": "[1.37.0-unstable, )",
+ "Nethermind.Trie": "[1.37.0-unstable, )",
"NonBlocking": "[2.1.2, )"
}
},
"nethermind.taiko": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Blockchain": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.Evm.Precompiles": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )",
- "Nethermind.JsonRpc": "[1.36.0-unstable, )",
- "Nethermind.Logging": "[1.36.0-unstable, )",
- "Nethermind.Merge.Plugin": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Json": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Blockchain": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.Evm.Precompiles": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )",
+ "Nethermind.JsonRpc": "[1.37.0-unstable, )",
+ "Nethermind.Logging": "[1.37.0-unstable, )",
+ "Nethermind.Merge.Plugin": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Json": "[1.37.0-unstable, )"
}
},
"nethermind.trie": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Db": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
"NonBlocking": "[2.1.2, )"
}
},
@@ -1157,39 +1780,39 @@
"type": "Project",
"dependencies": {
"Collections.Pooled": "[1.0.82, )",
- "Nethermind.Config": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Crypto": "[1.36.0-unstable, )",
- "Nethermind.Db": "[1.36.0-unstable, )",
- "Nethermind.Evm": "[1.36.0-unstable, )",
- "Nethermind.Network.Contract": "[1.36.0-unstable, )",
- "Nethermind.State": "[1.36.0-unstable, )",
+ "Nethermind.Config": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Crypto": "[1.37.0-unstable, )",
+ "Nethermind.Db": "[1.37.0-unstable, )",
+ "Nethermind.Evm": "[1.37.0-unstable, )",
+ "Nethermind.Network.Contract": "[1.37.0-unstable, )",
+ "Nethermind.State": "[1.37.0-unstable, )",
"NonBlocking": "[2.1.2, )"
}
},
"nethermind.upnp.plugin": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
+ "Nethermind.Api": "[1.37.0-unstable, )",
"Open.NAT.Core": "[2.1.0.5, )"
}
},
"nethermind.wallet": {
"type": "Project",
"dependencies": {
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.KeyStore": "[1.36.0-unstable, )",
- "Nethermind.Serialization.Rlp": "[1.36.0-unstable, )",
- "Nethermind.TxPool": "[1.36.0-unstable, )"
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.KeyStore": "[1.37.0-unstable, )",
+ "Nethermind.Serialization.Rlp": "[1.37.0-unstable, )",
+ "Nethermind.TxPool": "[1.37.0-unstable, )"
}
},
"nethermind.xdc": {
"type": "Project",
"dependencies": {
- "Nethermind.Api": "[1.36.0-unstable, )",
- "Nethermind.Consensus": "[1.36.0-unstable, )",
- "Nethermind.Core": "[1.36.0-unstable, )",
- "Nethermind.Init": "[1.36.0-unstable, )"
+ "Nethermind.Api": "[1.37.0-unstable, )",
+ "Nethermind.Consensus": "[1.37.0-unstable, )",
+ "Nethermind.Core": "[1.37.0-unstable, )",
+ "Nethermind.Init": "[1.37.0-unstable, )"
}
},
"AspNetCore.HealthChecks.UI": {
@@ -1200,7 +1823,8 @@
"dependencies": {
"AspNetCore.HealthChecks.UI.Data": "9.0.0",
"KubernetesClient": "15.0.1",
- "Microsoft.EntityFrameworkCore.Design": "8.0.11"
+ "Microsoft.EntityFrameworkCore.Design": "8.0.11",
+ "Microsoft.Extensions.Http": "8.0.0"
}
},
"AspNetCore.HealthChecks.UI.InMemory.Storage": {
@@ -1225,7 +1849,8 @@
"resolved": "10.0.0",
"contentHash": "ZjR/onUlP7BzQ7VBBigQepWLAyAzi3VRGX3pP6sBqkPRiT61fsTZqbTpRUKxo30TMgbs1o3y6bpLbETix4SJog==",
"dependencies": {
- "Autofac": "8.1.0"
+ "Autofac": "8.1.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1"
}
},
"BouncyCastle.Cryptography": {
@@ -1324,6 +1949,31 @@
"MathNet.Numerics": "5.0.0"
}
},
+ "Microsoft.AspNetCore.DataProtection": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "RKU345im2k3hqboK+2ZcBa6oReAUr1m4c/8kf/6/rATNjxVFvWmCMLIP4U1lHhYat+Zmv1TpOlCw+8/7xATRhA==",
+ "dependencies": {
+ "Microsoft.AspNetCore.Cryptography.Internal": "10.0.0",
+ "Microsoft.AspNetCore.DataProtection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Hosting.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "System.Security.Cryptography.Xml": "10.0.0"
+ }
+ },
+ "Microsoft.AspNetCore.DataProtection.Extensions": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "FRBizffEDpUVIkb0RnIgSzQmSuFa9mLEvbROakrkSzRythB/qubj8j4U0vuxyfAXrLSuQdsbogMHlCTPC/4QeQ==",
+ "dependencies": {
+ "Microsoft.AspNetCore.DataProtection": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection": "10.0.0"
+ }
+ },
"Microsoft.ClearScript.V8": {
"type": "CentralTransitive",
"requested": "[7.5.0, )",
@@ -1380,6 +2030,67 @@
"Microsoft.CodeAnalysis.Common": "[4.5.0]"
}
},
+ "Microsoft.Extensions.Caching.Memory": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "krK19MKp0BNiR9rpBDW7PKSrTMLVlifS9am3CVc4O1Jq6GWz0o4F+sw5OSL4L3mVd56W8l6JRgghUa2KB51vOw==",
+ "dependencies": {
+ "Microsoft.Extensions.Caching.Abstractions": "10.0.0",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.0",
+ "Microsoft.Extensions.Options": "10.0.0",
+ "Microsoft.Extensions.Primitives": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "f0RBabswJq+gRu5a+hWIobrLWiUYPKMhCD9WO3sYBAdSy3FFH14LMvLVFZc2kPSCimBLxSuitUhsd6tb0TAY6A==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "CentralTransitive",
+ "requested": "[8.0.0, )",
+ "resolved": "9.0.0",
+ "contentHash": "crjWyORoug0kK7RSNJBTeSE6VX8IQgLf3nUpTB9m62bPXp/tzbnOsnbe8TXEG0AASNaKZddnpHKw7fET8E++Pg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "9.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Options": "9.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "FU/IfjDfwaMuKr414SSQNTIti/69bHEMb+QKrskRb26oVqpx3lNFXMjs/RC9ZUuhBhcwDM2BwOgoMw+PZ+beqQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0"
+ }
+ },
+ "Microsoft.Extensions.Logging.Console": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "9.0.0",
+ "contentHash": "yDZ4zsjl7N0K+R/1QTNpXBd79Kaf4qNLHtjk4NaG82UtNg2Z6etJywwv6OarOv3Rp7ocU7uIaRY4CrzHRO/d3w==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Logging": "9.0.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
+ "Microsoft.Extensions.Logging.Configuration": "9.0.0",
+ "Microsoft.Extensions.Options": "9.0.0"
+ }
+ },
+ "Microsoft.Extensions.ObjectPool": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.0, )",
+ "resolved": "10.0.0",
+ "contentHash": "bpeCq0IYmVLACyEUMzFIOQX+zZUElG1t+nu1lSxthe7B+1oNYking7b91305+jNB6iwojp9fqTY9O+Nh7ULQxg=="
+ },
"Microsoft.IdentityModel.JsonWebTokens": {
"type": "CentralTransitive",
"requested": "[8.15.0, )",
@@ -1419,7 +2130,8 @@
"resolved": "1.0.2.76",
"contentHash": "bI9wc+xazOgsgibMvPaMWtQ4dNWktBBCo3fZeUVFgEsDBMwagl3GqIozx4D1I1GbozkhCpUD55Q2KGx0CuDHHQ==",
"dependencies": {
- "Nethermind.DotNetty.Common": "1.0.2.76"
+ "Nethermind.DotNetty.Common": "1.0.2.76",
+ "System.Runtime.CompilerServices.Unsafe": "5.0.0"
}
},
"Nethermind.DotNetty.Handlers": {
@@ -1456,6 +2168,9 @@
"resolved": "1.0.0-preview.45",
"contentHash": "OLV+fEkqbG+kFfQnFgkOloX8a1QPCJnTZfTkviOKgWo7vVlOnmePIvy0Tk963LVpmRmjreMCTvLLOh3yB1ZCJQ==",
"dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "9.0.0",
+ "Microsoft.Extensions.Logging": "9.0.0",
+ "Microsoft.Extensions.Logging.Console": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45",
"Nethermind.Libp2p.Protocols.Identify": "1.0.0-preview.45",
"Nethermind.Libp2p.Protocols.MDns": "1.0.0-preview.45",
@@ -1477,6 +2192,7 @@
"contentHash": "VK0g5fehGQbarfAzqwCFfNLhU7BBQBEkVypjt/ToOD619FhDMjqJJ1FuBPC0EP6Gmf2whG55cYnIBoGQdrNgtA==",
"dependencies": {
"Makaretu.Dns.Multicast": "0.27.0",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Nethermind.Libp2p.Core": "1.0.0-preview.45",
"Nethermind.Libp2p.Protocols.Pubsub": "1.0.0-preview.45"
}
@@ -1509,7 +2225,10 @@
"type": "CentralTransitive",
"requested": "[2.1.2, )",
"resolved": "2.1.2",
- "contentHash": "yTP24PcuFmUw1RxQgYmIMxvpAJ1ciT/zv8Sb7OZHTuM/x9Tupz+DvEqeu9HykSYmI3/bGuy1ZZ7k/rZgfuIAuw=="
+ "contentHash": "yTP24PcuFmUw1RxQgYmIMxvpAJ1ciT/zv8Sb7OZHTuM/x9Tupz+DvEqeu9HykSYmI3/bGuy1ZZ7k/rZgfuIAuw==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "4.3.0"
+ }
},
"Open.NAT.Core": {
"type": "CentralTransitive",
@@ -1524,9 +2243,15 @@
"contentHash": "WjVYiDxyZ3z00kuJJXuWJwRqkWfTrZF1v7qWz4mMASRP6AEhDCF4jMdCuAWkH1uPj00kkluONOc426Z//FcjDw==",
"dependencies": {
"BouncyCastle.Cryptography": "2.4.0",
+ "Microsoft.Extensions.Caching.Memory": "8.0.0",
+ "Microsoft.Extensions.DependencyInjection": "8.0.0",
+ "Microsoft.Extensions.Logging": "8.0.0",
+ "Microsoft.Extensions.Logging.Console": "8.0.0",
+ "Microsoft.Extensions.Options": "8.0.2",
"NBitcoin.Secp256k1": "3.1.5",
"PierTwo.Lantern.Discv5.Enr": "1.0.0-preview.6",
- "PierTwo.Lantern.Discv5.Rlp": "1.0.0-preview.6"
+ "PierTwo.Lantern.Discv5.Rlp": "1.0.0-preview.6",
+ "System.Threading.Tasks.Dataflow": "8.0.0"
}
},
"Polly": {
@@ -1538,6 +2263,16 @@
"Polly.Core": "8.6.4"
}
},
+ "prometheus-net": {
+ "type": "CentralTransitive",
+ "requested": "[8.2.1, )",
+ "resolved": "8.2.1",
+ "contentHash": "3wVgdEPOCBF752s2xps5T+VH+c9mJK8S8GKEDg49084P6JZMumTZI5Te6aJ9MQpX0sx7om6JOnBpIi7ZBmmiDQ==",
+ "dependencies": {
+ "Microsoft.Extensions.Http": "3.1.0",
+ "Microsoft.Extensions.ObjectPool": "7.0.0"
+ }
+ },
"prometheus-net.AspNetCore": {
"type": "CentralTransitive",
"requested": "[8.2.1, )",
@@ -1571,6 +2306,7 @@
"resolved": "10.0.0",
"contentHash": "0B+BzJ6pPMrRzJrVsttKf9MfDj6Syw9xoY+agcS9VssYQali1446+jTf5v1K94AMFUBxLXqDZlaTjO5edaI3jA==",
"dependencies": {
+ "System.Diagnostics.EventLog": "10.0.0",
"System.Security.Cryptography.ProtectedData": "10.0.0"
}
},
@@ -1595,6 +2331,7 @@
"resolved": "5.3.0",
"contentHash": "uhdDM+gruCEhHRCKCoyali1HJp0wSS/HBs5X9XZwULNKM2y5ML188TsvcEgWEFOx0NOaHfGNtfoC0cd1p2NOIg==",
"dependencies": {
+ "Microsoft.Extensions.Logging.Abstractions": "8.0.0",
"Microsoft.IO.RecyclableMemoryStream": "3.0.0",
"System.Reactive": "6.0.0"
}
@@ -1612,7 +2349,8 @@
"resolved": "2.46.6",
"contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
"dependencies": {
- "Grpc.Core.Api": "2.46.6"
+ "Grpc.Core.Api": "2.46.6",
+ "System.Memory": "4.5.3"
}
},
"libsodium": {
@@ -1620,11 +2358,1343 @@
"resolved": "1.0.20",
"contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
},
- "Tmds.LibC": {
+ "Microsoft.Win32.Registry": {
"type": "Transitive",
- "resolved": "0.2.0",
- "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
- },
+ "resolved": "5.0.0",
+ "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
+ "dependencies": {
+ "System.Security.AccessControl": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "runtime.any.System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "runtime.any.System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw=="
+ },
+ "runtime.any.System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ=="
+ },
+ "runtime.any.System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ=="
+ },
+ "runtime.any.System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA=="
+ },
+ "runtime.any.System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg=="
+ },
+ "runtime.any.System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ=="
+ },
+ "runtime.any.System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0"
+ }
+ },
+ "runtime.any.System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ=="
+ },
+ "runtime.any.System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw=="
+ },
+ "runtime.any.System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ=="
+ },
+ "runtime.any.System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w=="
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
+ },
+ "runtime.unix.System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Collections": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Diagnostics.Debug": "4.3.0"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Globalization": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Threading.Tasks": "4.0.11",
+ "runtime.any.System.IO": "4.3.0"
+ }
+ },
+ "System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "runtime.unix.System.Private.Uri": "4.3.0"
+ }
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.IO": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Extensions": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Primitives": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Globalization": "4.0.11",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Resources.ResourceManager": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "Microsoft.NETCore.Targets": "1.1.3",
+ "runtime.any.System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Handles": "4.0.1",
+ "runtime.any.System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.Security.AccessControl": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UPWqLSygJlFerRi9XNIuM0a1VC8gHUIufyP24xQ0sc+XimqUAEcjpOz9DhKpyDjH+5B/wO3RpC0KpkEeDj/ddg=="
+ },
+ "System.Security.Principal.Windows": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "Tmds.LibC": {
+ "type": "Transitive",
+ "resolved": "0.2.0",
+ "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ },
+ "Ckzg.Bindings": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.5.1542, )",
+ "resolved": "2.1.5.1542",
+ "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ=="
+ },
+ "Microsoft.ClearScript.V8.Native.linux-arm64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "UU+3Bef3UnwQgP8hKobT09ucYuYubVFiseAsuRUvmjvOBVu7yHRES+nXBNYSvDi88fMTp/HBUknpYQdrfoDemQ=="
+ },
+ "Microsoft.ClearScript.V8.Native.linux-x64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "snoN9oRwKqShA32IsuCanLjNtP8hros2WOrOBL7g+ED3AV40qwrsbfKwWq37BzogrfsF1aEVoDkBpE19Az7DVQ=="
+ },
+ "Microsoft.ClearScript.V8.Native.osx-arm64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "CkMgeX0I0+bXUzoaVoJdV86/k0H2PEukqCoZ8zQ28msB6YHeRX6FJTfvOQ0l6UTX5HaBHGG3CWUI04uBYe6M+A=="
+ },
+ "Microsoft.ClearScript.V8.Native.osx-x64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "yXoXLWKJJgW5V6ez1aMa+ZS2nCef0X4iTYzPS9bTSYl9y7D4R2Ie2KrfR8nLO2rhOKimIMx3MH49Zh1CYruN/g=="
+ },
+ "Microsoft.ClearScript.V8.Native.win-x64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "DKMxDLboTNflYkwDQ/ELrSf1vXTpew5UZ8xzrXSVKYFBU570VA6NKh1etEGhufuCuDyU7Je5L2g6H+19Dbl+tA=="
+ },
+ "Nethermind.Crypto.Bls": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.5, )",
+ "resolved": "1.0.5",
+ "contentHash": "SYdQOFVVcC3R3VAm9Dv+u4Mc1yqHZETxt4tN3a+AFeOnEtUmpcjwVwYkkiiUIIrr6vQVVOUuwsDmaa9l3u45IQ=="
+ },
+ "Nethermind.Crypto.SecP256k1": {
+ "type": "CentralTransitive",
+ "requested": "[1.5.0, )",
+ "resolved": "1.5.0",
+ "contentHash": "+mNlEgN1gYDB6f4jRcYssaE6/AlSoPr7eLDQHQoX+tXcnGRzgnArezPwz82TsWxruQGDh5h9Qfowa0xt4Xz59g=="
+ },
+ "Nethermind.Crypto.SecP256r1": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.0-preview.6, )",
+ "resolved": "1.0.0-preview.6",
+ "contentHash": "wFfpg1ofZz5nsjN8TAKUg0mdUCskmOUO0lFk3LcoeRkVnQ5Rw2rYzsJxgPFfnxAABH/EPPs62S7oF8E0Ayjjeg=="
+ },
+ "Nethermind.GmpBindings": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "EE12z2k4ku0ugfI01utaQR8EbBoEMLI4QAKKGrfz5Fvbw/YtXTqDDzvKtBTleOB9YBH7oTpH9T9ZFtKgKZMj2g=="
+ },
+ "Nethermind.MclBindings": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg=="
+ },
+ "RocksDB": {
+ "type": "CentralTransitive",
+ "requested": "[10.4.2.62659, 10.4.2.62659]",
+ "resolved": "10.4.2.62659",
+ "contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
+ }
+ },
+ "net10.0/linux-x64": {
+ "Grpc.Core": {
+ "type": "Transitive",
+ "resolved": "2.46.6",
+ "contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
+ "dependencies": {
+ "Grpc.Core.Api": "2.46.6",
+ "System.Memory": "4.5.3"
+ }
+ },
+ "libsodium": {
+ "type": "Transitive",
+ "resolved": "1.0.20",
+ "contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
+ },
+ "Microsoft.Win32.Registry": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
+ "dependencies": {
+ "System.Security.AccessControl": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "runtime.any.System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "runtime.any.System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw=="
+ },
+ "runtime.any.System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ=="
+ },
+ "runtime.any.System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ=="
+ },
+ "runtime.any.System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA=="
+ },
+ "runtime.any.System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg=="
+ },
+ "runtime.any.System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ=="
+ },
+ "runtime.any.System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0"
+ }
+ },
+ "runtime.any.System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ=="
+ },
+ "runtime.any.System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw=="
+ },
+ "runtime.any.System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ=="
+ },
+ "runtime.any.System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w=="
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
+ },
+ "runtime.unix.System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Collections": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Diagnostics.Debug": "4.3.0"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Globalization": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Threading.Tasks": "4.0.11",
+ "runtime.any.System.IO": "4.3.0"
+ }
+ },
+ "System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "runtime.unix.System.Private.Uri": "4.3.0"
+ }
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.IO": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Extensions": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Primitives": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Globalization": "4.0.11",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Resources.ResourceManager": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "Microsoft.NETCore.Targets": "1.1.3",
+ "runtime.any.System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Handles": "4.0.1",
+ "runtime.any.System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.Security.AccessControl": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UPWqLSygJlFerRi9XNIuM0a1VC8gHUIufyP24xQ0sc+XimqUAEcjpOz9DhKpyDjH+5B/wO3RpC0KpkEeDj/ddg=="
+ },
+ "System.Security.Principal.Windows": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "Tmds.LibC": {
+ "type": "Transitive",
+ "resolved": "0.2.0",
+ "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ },
+ "Ckzg.Bindings": {
+ "type": "CentralTransitive",
+ "requested": "[2.1.5.1542, )",
+ "resolved": "2.1.5.1542",
+ "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ=="
+ },
+ "Microsoft.ClearScript.V8.Native.linux-arm64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "UU+3Bef3UnwQgP8hKobT09ucYuYubVFiseAsuRUvmjvOBVu7yHRES+nXBNYSvDi88fMTp/HBUknpYQdrfoDemQ=="
+ },
+ "Microsoft.ClearScript.V8.Native.linux-x64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "snoN9oRwKqShA32IsuCanLjNtP8hros2WOrOBL7g+ED3AV40qwrsbfKwWq37BzogrfsF1aEVoDkBpE19Az7DVQ=="
+ },
+ "Microsoft.ClearScript.V8.Native.osx-arm64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "CkMgeX0I0+bXUzoaVoJdV86/k0H2PEukqCoZ8zQ28msB6YHeRX6FJTfvOQ0l6UTX5HaBHGG3CWUI04uBYe6M+A=="
+ },
+ "Microsoft.ClearScript.V8.Native.osx-x64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "yXoXLWKJJgW5V6ez1aMa+ZS2nCef0X4iTYzPS9bTSYl9y7D4R2Ie2KrfR8nLO2rhOKimIMx3MH49Zh1CYruN/g=="
+ },
+ "Microsoft.ClearScript.V8.Native.win-x64": {
+ "type": "CentralTransitive",
+ "requested": "[7.5.0, )",
+ "resolved": "7.5.0",
+ "contentHash": "DKMxDLboTNflYkwDQ/ELrSf1vXTpew5UZ8xzrXSVKYFBU570VA6NKh1etEGhufuCuDyU7Je5L2g6H+19Dbl+tA=="
+ },
+ "Nethermind.Crypto.Bls": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.5, )",
+ "resolved": "1.0.5",
+ "contentHash": "SYdQOFVVcC3R3VAm9Dv+u4Mc1yqHZETxt4tN3a+AFeOnEtUmpcjwVwYkkiiUIIrr6vQVVOUuwsDmaa9l3u45IQ=="
+ },
+ "Nethermind.Crypto.SecP256k1": {
+ "type": "CentralTransitive",
+ "requested": "[1.5.0, )",
+ "resolved": "1.5.0",
+ "contentHash": "+mNlEgN1gYDB6f4jRcYssaE6/AlSoPr7eLDQHQoX+tXcnGRzgnArezPwz82TsWxruQGDh5h9Qfowa0xt4Xz59g=="
+ },
+ "Nethermind.Crypto.SecP256r1": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.0-preview.6, )",
+ "resolved": "1.0.0-preview.6",
+ "contentHash": "wFfpg1ofZz5nsjN8TAKUg0mdUCskmOUO0lFk3LcoeRkVnQ5Rw2rYzsJxgPFfnxAABH/EPPs62S7oF8E0Ayjjeg=="
+ },
+ "Nethermind.GmpBindings": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "EE12z2k4ku0ugfI01utaQR8EbBoEMLI4QAKKGrfz5Fvbw/YtXTqDDzvKtBTleOB9YBH7oTpH9T9ZFtKgKZMj2g=="
+ },
+ "Nethermind.MclBindings": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg=="
+ },
+ "RocksDB": {
+ "type": "CentralTransitive",
+ "requested": "[10.4.2.62659, 10.4.2.62659]",
+ "resolved": "10.4.2.62659",
+ "contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
+ }
+ },
+ "net10.0/osx-arm64": {
+ "Grpc.Core": {
+ "type": "Transitive",
+ "resolved": "2.46.6",
+ "contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
+ "dependencies": {
+ "Grpc.Core.Api": "2.46.6",
+ "System.Memory": "4.5.3"
+ }
+ },
+ "libsodium": {
+ "type": "Transitive",
+ "resolved": "1.0.20",
+ "contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
+ },
+ "Microsoft.Win32.Registry": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
+ "dependencies": {
+ "System.Security.AccessControl": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "runtime.any.System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "runtime.any.System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw=="
+ },
+ "runtime.any.System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ=="
+ },
+ "runtime.any.System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ=="
+ },
+ "runtime.any.System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA=="
+ },
+ "runtime.any.System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg=="
+ },
+ "runtime.any.System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ=="
+ },
+ "runtime.any.System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0"
+ }
+ },
+ "runtime.any.System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ=="
+ },
+ "runtime.any.System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw=="
+ },
+ "runtime.any.System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ=="
+ },
+ "runtime.any.System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w=="
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
+ },
+ "runtime.unix.System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Collections": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Diagnostics.Debug": "4.3.0"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Globalization": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Threading.Tasks": "4.0.11",
+ "runtime.any.System.IO": "4.3.0"
+ }
+ },
+ "System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "runtime.unix.System.Private.Uri": "4.3.0"
+ }
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.IO": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Extensions": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Primitives": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Globalization": "4.0.11",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Resources.ResourceManager": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "Microsoft.NETCore.Targets": "1.1.3",
+ "runtime.any.System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Handles": "4.0.1",
+ "runtime.any.System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.Security.AccessControl": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UPWqLSygJlFerRi9XNIuM0a1VC8gHUIufyP24xQ0sc+XimqUAEcjpOz9DhKpyDjH+5B/wO3RpC0KpkEeDj/ddg=="
+ },
+ "System.Security.Principal.Windows": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "Tmds.LibC": {
+ "type": "Transitive",
+ "resolved": "0.2.0",
+ "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ },
"Ckzg.Bindings": {
"type": "CentralTransitive",
"requested": "[2.1.5.1542, )",
@@ -1685,32 +3755,415 @@
"resolved": "1.0.3",
"contentHash": "EE12z2k4ku0ugfI01utaQR8EbBoEMLI4QAKKGrfz5Fvbw/YtXTqDDzvKtBTleOB9YBH7oTpH9T9ZFtKgKZMj2g=="
},
- "Nethermind.MclBindings": {
- "type": "CentralTransitive",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg=="
+ "Nethermind.MclBindings": {
+ "type": "CentralTransitive",
+ "requested": "[1.0.3, )",
+ "resolved": "1.0.3",
+ "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg=="
+ },
+ "RocksDB": {
+ "type": "CentralTransitive",
+ "requested": "[10.4.2.62659, 10.4.2.62659]",
+ "resolved": "10.4.2.62659",
+ "contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
+ }
+ },
+ "net10.0/osx-x64": {
+ "Grpc.Core": {
+ "type": "Transitive",
+ "resolved": "2.46.6",
+ "contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
+ "dependencies": {
+ "Grpc.Core.Api": "2.46.6",
+ "System.Memory": "4.5.3"
+ }
+ },
+ "libsodium": {
+ "type": "Transitive",
+ "resolved": "1.0.20",
+ "contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
+ },
+ "Microsoft.Win32.Registry": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
+ "dependencies": {
+ "System.Security.AccessControl": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "runtime.any.System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "runtime.any.System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw=="
+ },
+ "runtime.any.System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ=="
+ },
+ "runtime.any.System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ=="
+ },
+ "runtime.any.System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA=="
+ },
+ "runtime.any.System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg=="
+ },
+ "runtime.any.System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ=="
+ },
+ "runtime.any.System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0"
+ }
+ },
+ "runtime.any.System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ=="
+ },
+ "runtime.any.System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw=="
+ },
+ "runtime.any.System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ=="
+ },
+ "runtime.any.System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w=="
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
+ },
+ "runtime.unix.System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==",
+ "dependencies": {
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "runtime.unix.System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Collections": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Diagnostics.Debug": "4.3.0"
+ }
+ },
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Globalization": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Threading.Tasks": "4.0.11",
+ "runtime.any.System.IO": "4.3.0"
+ }
+ },
+ "System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "runtime.unix.System.Private.Uri": "4.3.0"
+ }
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.IO": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Extensions": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Primitives": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Globalization": "4.0.11",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Resources.ResourceManager": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "Microsoft.NETCore.Targets": "1.1.3",
+ "runtime.any.System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.unix.System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Handles": "4.0.1",
+ "runtime.any.System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.Security.AccessControl": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UPWqLSygJlFerRi9XNIuM0a1VC8gHUIufyP24xQ0sc+XimqUAEcjpOz9DhKpyDjH+5B/wO3RpC0KpkEeDj/ddg=="
+ },
+ "System.Security.Principal.Windows": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
},
- "RocksDB": {
- "type": "CentralTransitive",
- "requested": "[10.4.2.62659, 10.4.2.62659]",
- "resolved": "10.4.2.62659",
- "contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
- }
- },
- "net10.0/linux-x64": {
- "Grpc.Core": {
+ "System.Text.Encoding": {
"type": "Transitive",
- "resolved": "2.46.6",
- "contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
+ "resolved": "4.0.11",
+ "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
"dependencies": {
- "Grpc.Core.Api": "2.46.6"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Text.Encoding": "4.3.0"
}
},
- "libsodium": {
+ "System.Text.Encoding.CodePages": {
"type": "Transitive",
- "resolved": "1.0.20",
- "contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Threading.Tasks": "4.3.0"
+ }
},
"Tmds.LibC": {
"type": "Transitive",
@@ -1790,13 +4243,14 @@
"contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
}
},
- "net10.0/osx-arm64": {
+ "net10.0/win-x64": {
"Grpc.Core": {
"type": "Transitive",
"resolved": "2.46.6",
"contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
"dependencies": {
- "Grpc.Core.Api": "2.46.6"
+ "Grpc.Core.Api": "2.46.6",
+ "System.Memory": "4.5.3"
}
},
"libsodium": {
@@ -1804,189 +4258,297 @@
"resolved": "1.0.20",
"contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
},
- "Tmds.LibC": {
+ "Microsoft.Win32.Registry": {
"type": "Transitive",
- "resolved": "0.2.0",
- "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ "resolved": "5.0.0",
+ "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
+ "dependencies": {
+ "System.Security.AccessControl": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
},
- "Ckzg.Bindings": {
- "type": "CentralTransitive",
- "requested": "[2.1.5.1542, )",
- "resolved": "2.1.5.1542",
- "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ=="
+ "runtime.any.System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
},
- "Microsoft.ClearScript.V8.Native.linux-arm64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "UU+3Bef3UnwQgP8hKobT09ucYuYubVFiseAsuRUvmjvOBVu7yHRES+nXBNYSvDi88fMTp/HBUknpYQdrfoDemQ=="
+ "runtime.any.System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw=="
},
- "Microsoft.ClearScript.V8.Native.linux-x64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "snoN9oRwKqShA32IsuCanLjNtP8hros2WOrOBL7g+ED3AV40qwrsbfKwWq37BzogrfsF1aEVoDkBpE19Az7DVQ=="
+ "runtime.any.System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ=="
},
- "Microsoft.ClearScript.V8.Native.osx-arm64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "CkMgeX0I0+bXUzoaVoJdV86/k0H2PEukqCoZ8zQ28msB6YHeRX6FJTfvOQ0l6UTX5HaBHGG3CWUI04uBYe6M+A=="
+ "runtime.any.System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ=="
},
- "Microsoft.ClearScript.V8.Native.osx-x64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "yXoXLWKJJgW5V6ez1aMa+ZS2nCef0X4iTYzPS9bTSYl9y7D4R2Ie2KrfR8nLO2rhOKimIMx3MH49Zh1CYruN/g=="
+ "runtime.any.System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA=="
},
- "Microsoft.ClearScript.V8.Native.win-x64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "DKMxDLboTNflYkwDQ/ELrSf1vXTpew5UZ8xzrXSVKYFBU570VA6NKh1etEGhufuCuDyU7Je5L2g6H+19Dbl+tA=="
+ "runtime.any.System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg=="
},
- "Nethermind.Crypto.Bls": {
- "type": "CentralTransitive",
- "requested": "[1.0.5, )",
- "resolved": "1.0.5",
- "contentHash": "SYdQOFVVcC3R3VAm9Dv+u4Mc1yqHZETxt4tN3a+AFeOnEtUmpcjwVwYkkiiUIIrr6vQVVOUuwsDmaa9l3u45IQ=="
+ "runtime.any.System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ=="
},
- "Nethermind.Crypto.SecP256k1": {
- "type": "CentralTransitive",
- "requested": "[1.5.0, )",
- "resolved": "1.5.0",
- "contentHash": "+mNlEgN1gYDB6f4jRcYssaE6/AlSoPr7eLDQHQoX+tXcnGRzgnArezPwz82TsWxruQGDh5h9Qfowa0xt4Xz59g=="
+ "runtime.any.System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==",
+ "dependencies": {
+ "System.Private.Uri": "4.3.0"
+ }
},
- "Nethermind.Crypto.SecP256r1": {
- "type": "CentralTransitive",
- "requested": "[1.0.0-preview.6, )",
- "resolved": "1.0.0-preview.6",
- "contentHash": "wFfpg1ofZz5nsjN8TAKUg0mdUCskmOUO0lFk3LcoeRkVnQ5Rw2rYzsJxgPFfnxAABH/EPPs62S7oF8E0Ayjjeg=="
+ "runtime.any.System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ=="
},
- "Nethermind.GmpBindings": {
- "type": "CentralTransitive",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "EE12z2k4ku0ugfI01utaQR8EbBoEMLI4QAKKGrfz5Fvbw/YtXTqDDzvKtBTleOB9YBH7oTpH9T9ZFtKgKZMj2g=="
+ "runtime.any.System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw=="
},
- "Nethermind.MclBindings": {
- "type": "CentralTransitive",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg=="
+ "runtime.any.System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ=="
},
- "RocksDB": {
- "type": "CentralTransitive",
- "requested": "[10.4.2.62659, 10.4.2.62659]",
- "resolved": "10.4.2.62659",
- "contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
- }
- },
- "net10.0/osx-x64": {
- "Grpc.Core": {
+ "runtime.any.System.Threading.Tasks": {
"type": "Transitive",
- "resolved": "2.46.6",
- "contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
+ "resolved": "4.3.0",
+ "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w=="
+ },
+ "runtime.win.System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "hHHP0WCStene2jjeYcuDkETozUYF/3sHVRHAEOgS3L15hlip24ssqCTnJC28Z03Wpo078oMcJd0H4egD2aJI8g=="
+ },
+ "runtime.win.System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "RkgHVhUPvzZxuUubiZe8yr/6CypRVXj0VBzaR8hsqQ8f+rUo7e4PWrHTLOCjd8fBMGWCrY//fi7Ku3qXD7oHRw==",
"dependencies": {
- "Grpc.Core.Api": "2.46.6"
+ "System.Private.Uri": "4.3.0"
}
},
- "libsodium": {
+ "System.Collections": {
"type": "Transitive",
- "resolved": "1.0.20",
- "contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
+ "resolved": "4.0.11",
+ "contentHash": "YUJGz6eFKqS0V//mLt25vFGrrCvOnsXjlvFQs+KimpwNxug9x0Pzy4PlFMU3Q2IzqAa9G2L4LsK3+9vCBK7oTg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Collections": "4.3.0"
+ }
},
- "Tmds.LibC": {
+ "System.Diagnostics.Debug": {
"type": "Transitive",
- "resolved": "0.2.0",
- "contentHash": "+RvLuNHOLW7cxzgDe9yHLoayBgjsuH2/gJtJnuVMxweKrxxYT6TwQNAmt06SFWpjwk68aRcwwD4FfMMA6tZvVA=="
+ "resolved": "4.0.11",
+ "contentHash": "w5U95fVKHY4G8ASs/K5iK3J5LY+/dLFd4vKejsnI/ZhBsWS9hQakfx3Zr7lRWKg4tAw9r4iktyvsTagWkqYCiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.win.System.Diagnostics.Debug": "4.3.0"
+ }
},
- "Ckzg.Bindings": {
- "type": "CentralTransitive",
- "requested": "[2.1.5.1542, )",
- "resolved": "2.1.5.1542",
- "contentHash": "GFXmOjg5fZ8s+836/HdKiyXbJ+J73wVX6hNmUE6Isb1rA8dI2SMLeW1m48s+ZNIPN9ENJb8Daq1GwmMjBGjUVQ=="
+ "System.Diagnostics.EventLog": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "uaFRda9NjtbJRkdx311eXlAA3n2em7223c1A8d1VWyl+4FL9vkG7y2lpPfBU9HYdj/9KgdRNdn1vFK8ZYCYT/A=="
},
- "Microsoft.ClearScript.V8.Native.linux-arm64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "UU+3Bef3UnwQgP8hKobT09ucYuYubVFiseAsuRUvmjvOBVu7yHRES+nXBNYSvDi88fMTp/HBUknpYQdrfoDemQ=="
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "B95h0YLEL2oSnwF/XjqSWKnwKOy/01VWkNlsCeMTFJLLabflpGV26nK164eRs5GiaRSBGpOxQ3pKoSnnyZN5pg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Globalization": "4.3.0"
+ }
},
- "Microsoft.ClearScript.V8.Native.linux-x64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "snoN9oRwKqShA32IsuCanLjNtP8hros2WOrOBL7g+ED3AV40qwrsbfKwWq37BzogrfsF1aEVoDkBpE19Az7DVQ=="
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "3KlTJceQc3gnGIaHZ7UBZO26SHL1SHE4ddrmiwumFnId+CEHP+O8r386tZKaE6zlk5/mF8vifMBzHj9SaXN+mQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Text.Encoding": "4.0.11",
+ "System.Threading.Tasks": "4.0.11",
+ "runtime.any.System.IO": "4.3.0"
+ }
},
- "Microsoft.ClearScript.V8.Native.osx-arm64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "CkMgeX0I0+bXUzoaVoJdV86/k0H2PEukqCoZ8zQ28msB6YHeRX6FJTfvOQ0l6UTX5HaBHGG3CWUI04uBYe6M+A=="
+ "System.Private.Uri": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
},
- "Microsoft.ClearScript.V8.Native.osx-x64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "yXoXLWKJJgW5V6ez1aMa+ZS2nCef0X4iTYzPS9bTSYl9y7D4R2Ie2KrfR8nLO2rhOKimIMx3MH49Zh1CYruN/g=="
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "JCKANJ0TI7kzoQzuwB/OoJANy1Lg338B6+JVacPl4TpUwi3cReg3nMLplMq2uqYfHFQpKIlHAUVAJlImZz/4ng==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.IO": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection": "4.3.0"
+ }
},
- "Microsoft.ClearScript.V8.Native.win-x64": {
- "type": "CentralTransitive",
- "requested": "[7.5.0, )",
- "resolved": "7.5.0",
- "contentHash": "DKMxDLboTNflYkwDQ/ELrSf1vXTpew5UZ8xzrXSVKYFBU570VA6NKh1etEGhufuCuDyU7Je5L2g6H+19Dbl+tA=="
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "GYrtRsZcMuHF3sbmRHfMYpvxZoIN2bQGrYGerUiWLEkqdEUQZhH3TRSaC/oI4wO0II1RKBPlpIa1TOMxIcOOzQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Extensions": "4.3.0"
+ }
},
- "Nethermind.Crypto.Bls": {
- "type": "CentralTransitive",
- "requested": "[1.0.5, )",
- "resolved": "1.0.5",
- "contentHash": "SYdQOFVVcC3R3VAm9Dv+u4Mc1yqHZETxt4tN3a+AFeOnEtUmpcjwVwYkkiiUIIrr6vQVVOUuwsDmaa9l3u45IQ=="
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "4inTox4wTBaDhB7V3mPvp9XlCbeGYWVEM9/fXALd52vNEAVisc1BoVWQPuUuD0Ga//dNbA/WeMy9u9mzLxGTHQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Reflection.Primitives": "4.3.0"
+ }
},
- "Nethermind.Crypto.SecP256k1": {
- "type": "CentralTransitive",
- "requested": "[1.5.0, )",
- "resolved": "1.5.0",
- "contentHash": "+mNlEgN1gYDB6f4jRcYssaE6/AlSoPr7eLDQHQoX+tXcnGRzgnArezPwz82TsWxruQGDh5h9Qfowa0xt4Xz59g=="
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "TxwVeUNoTgUOdQ09gfTjvW411MF+w9MBYL7AtNVc+HtBCFlutPLhUCdZjNkjbhj3bNQWMdHboF0KIWEOjJssbA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Globalization": "4.0.11",
+ "System.Reflection": "4.1.0",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Resources.ResourceManager": "4.3.0"
+ }
},
- "Nethermind.Crypto.SecP256r1": {
- "type": "CentralTransitive",
- "requested": "[1.0.0-preview.6, )",
- "resolved": "1.0.0-preview.6",
- "contentHash": "wFfpg1ofZz5nsjN8TAKUg0mdUCskmOUO0lFk3LcoeRkVnQ5Rw2rYzsJxgPFfnxAABH/EPPs62S7oF8E0Ayjjeg=="
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.1",
+ "contentHash": "abhfv1dTK6NXOmu4bgHIONxHyEqFjW8HwXPmpY9gmll+ix9UNo4XDcmzJn6oLooftxNssVHdJC1pGT9jkSynQg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.1",
+ "Microsoft.NETCore.Targets": "1.1.3",
+ "runtime.any.System.Runtime": "4.3.0"
+ }
},
- "Nethermind.GmpBindings": {
- "type": "CentralTransitive",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "EE12z2k4ku0ugfI01utaQR8EbBoEMLI4QAKKGrfz5Fvbw/YtXTqDDzvKtBTleOB9YBH7oTpH9T9ZFtKgKZMj2g=="
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.1.0",
+ "contentHash": "CUOHjTT/vgP0qGW22U4/hDlOqXmcPq5YicBaXdUR2UiUoLwBT+olO6we4DVbq57jeX5uXH2uerVZhf0qGj+sVQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.win.System.Runtime.Extensions": "4.3.0"
+ }
},
- "Nethermind.MclBindings": {
- "type": "CentralTransitive",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "hgT2oiMFqItNXv5vzIbhhlgqPJK4qnOHaYmUiR4jJsaWiqDRH05YtqYeMQq2+oyBOf8REtuGOW5RZ7+agRSEbg=="
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.0.1",
+ "contentHash": "nCJvEKguXEvk2ymk1gqj625vVnlK3/xdGzx0vOKicQkoquaTBJTP13AIYkocSUwHCLNBwUbXTqTWGDxBTWpt7g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Runtime.Handles": "4.3.0"
+ }
},
- "RocksDB": {
- "type": "CentralTransitive",
- "requested": "[10.4.2.62659, 10.4.2.62659]",
- "resolved": "10.4.2.62659",
- "contentHash": "+ZY7koKclaRz7+3QiCbXprWK4++Cwh0Hhqj+5Z5fcZpQvoIoo+iM9iAdCo+W5ha9XOLeI0YWbi9nZt12dNVBMg=="
- }
- },
- "net10.0/win-x64": {
- "Grpc.Core": {
+ "System.Runtime.InteropServices": {
"type": "Transitive",
- "resolved": "2.46.6",
- "contentHash": "ZoRg3KmOJ2urTF4+u3H0b1Yv10xzz2Y/flFWS2tnRmj8dbKLeiJaSRqu4LOBD3ova90evqLkVZ85kUkC4JT4lw==",
+ "resolved": "4.1.0",
+ "contentHash": "16eu3kjHS633yYdkjwShDHZLRNMKVi/s0bY8ODiqJ2RfMhDMAwxZaUaWVnZ2P71kr/or+X9o/xFWtNqz8ivieQ==",
"dependencies": {
- "Grpc.Core.Api": "2.46.6"
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Reflection": "4.1.0",
+ "System.Reflection.Primitives": "4.0.1",
+ "System.Runtime": "4.1.0",
+ "System.Runtime.Handles": "4.0.1",
+ "runtime.any.System.Runtime.InteropServices": "4.3.0"
}
},
- "libsodium": {
+ "System.Security.AccessControl": {
"type": "Transitive",
- "resolved": "1.0.20",
- "contentHash": "fMO6HpAbvLagobzBH6eU36riWF01lCAweX34D5eugqjuXA+WS5MnV1ngE+2Sw3LvGvxZlmyLp9416t57dMZ5og=="
+ "resolved": "5.0.0",
+ "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "5.0.0",
+ "System.Security.Principal.Windows": "5.0.0"
+ }
+ },
+ "System.Security.Cryptography.Pkcs": {
+ "type": "Transitive",
+ "resolved": "10.0.0",
+ "contentHash": "UPWqLSygJlFerRi9XNIuM0a1VC8gHUIufyP24xQ0sc+XimqUAEcjpOz9DhKpyDjH+5B/wO3RpC0KpkEeDj/ddg=="
+ },
+ "System.Security.Principal.Windows": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "U3gGeMlDZXxCEiY4DwVLSacg+DFWCvoiX+JThA/rvw37Sqrku7sEFeVBBBMBnfB6FeZHsyDx85HlKL19x0HtZA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.0.11",
+ "contentHash": "k1S4Gc6IGwtHGT8188RSeGaX86Qw/wnrgNLshJvsdNUOPP9etMmo8S07c+UlOAx4K/xLuN9ivA1bD0LVurtIxQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1",
+ "Microsoft.NETCore.Targets": "1.0.1",
+ "System.Runtime": "4.1.0",
+ "runtime.any.System.Threading.Tasks": "4.3.0"
+ }
},
"Tmds.LibC": {
"type": "Transitive",
diff --git a/src/Nethermind/Nethermind.State.Test/Nethermind.State.Test.csproj b/src/Nethermind/Nethermind.State.Test/Nethermind.State.Test.csproj
index 4d0fd2ba57d..c1a4530f927 100644
--- a/src/Nethermind/Nethermind.State.Test/Nethermind.State.Test.csproj
+++ b/src/Nethermind/Nethermind.State.Test/Nethermind.State.Test.csproj
@@ -1,7 +1,7 @@
-
+
Nethermind.Store.Test
diff --git a/src/Nethermind/Nethermind.State.Test/SpmcRingBufferTests.cs b/src/Nethermind/Nethermind.State.Test/SpmcRingBufferTests.cs
new file mode 100644
index 00000000000..84f10cf8057
--- /dev/null
+++ b/src/Nethermind/Nethermind.State.Test/SpmcRingBufferTests.cs
@@ -0,0 +1,55 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using FluentAssertions;
+using Nethermind.State;
+using NUnit.Framework;
+
+namespace Nethermind.Store.Test;
+
+public class SpmcRingBufferTests
+{
+
+ [Test]
+ public void SmokeTest()
+ {
+ SpmcRingBuffer jobQueue = new SpmcRingBuffer(16);
+
+ jobQueue.TryEnqueue(1);
+ jobQueue.TryEnqueue(2);
+ jobQueue.TryEnqueue(3);
+ jobQueue.TryEnqueue(4);
+ jobQueue.TryEnqueue(5);
+
+ jobQueue.TryDequeue(out int j).Should().BeTrue();
+ j.Should().Be(1);
+ jobQueue.TryDequeue(out j).Should().BeTrue();
+ j.Should().Be(2);
+ jobQueue.TryDequeue(out j).Should().BeTrue();
+ j.Should().Be(3);
+ jobQueue.TryDequeue(out j).Should().BeTrue();
+ j.Should().Be(4);
+ jobQueue.TryDequeue(out j).Should().BeTrue();
+ j.Should().Be(5);
+ }
+
+ [Test]
+ public void RollingSmokeTest()
+ {
+ SpmcRingBuffer jobQueue = new SpmcRingBuffer(16);
+
+ jobQueue.TryEnqueue(1);
+ jobQueue.TryEnqueue(2);
+ jobQueue.TryEnqueue(3);
+ jobQueue.TryEnqueue(4);
+ jobQueue.TryEnqueue(5);
+
+ int j = 0;
+ for (int i = 0; i < 100; i++)
+ {
+ jobQueue.TryDequeue(out j).Should().BeTrue();
+ j.Should().Be(i + 1);
+ jobQueue.TryEnqueue(i + 5 + 1).Should().BeTrue();
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs b/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs
index cc25eea210a..d359da04eb0 100644
--- a/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs
+++ b/src/Nethermind/Nethermind.State.Test/StorageProviderTests.cs
@@ -760,6 +760,11 @@ public void Commit(long blockNumber)
{
baseScope.Commit(blockNumber);
}
+
+ public void HintSet(Address address)
+ {
+
+ }
}
private class WriteBatchDecorator(
diff --git a/src/Nethermind/Nethermind.State/Flat/CachedResource.cs b/src/Nethermind/Nethermind.State/Flat/CachedResource.cs
new file mode 100644
index 00000000000..1c3b82f3305
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/CachedResource.cs
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Concurrent;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Crypto;
+using Nethermind.Int256;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat;
+
+public record CachedResource(
+ ConcurrentDictionary TrieWarmerLoadedNodes,
+ ConcurrentDictionary<(Hash256AsKey, TreePath), TrieNode> LoadedStorageNodes,
+ ConcurrentDictionary<(AddressAsKey, UInt256?), bool> PrewarmedAddresses
+)
+{
+ public void Clear()
+ {
+ TrieWarmerLoadedNodes.NoResizeClear();
+ LoadedStorageNodes.NoResizeClear();
+ PrewarmedAddresses.NoResizeClear();
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/FlatDbColumns.cs b/src/Nethermind/Nethermind.State/Flat/FlatDbColumns.cs
new file mode 100644
index 00000000000..2d94c7a14cf
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/FlatDbColumns.cs
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+namespace Nethermind.State.Flat;
+
+public enum FlatDbColumns
+{
+ Metadata,
+ State,
+ Storage,
+ StateNodes,
+ StateTopNodes,
+ StorageNodes,
+ StorageTopNodes,
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/FlatDiffRepository.cs b/src/Nethermind/Nethermind.State/Flat/FlatDiffRepository.cs
new file mode 100644
index 00000000000..33e1ca6757b
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/FlatDiffRepository.cs
@@ -0,0 +1,906 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Channels;
+using System.Threading.Tasks;
+using Nethermind.Config;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Int256;
+using Nethermind.Logging;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.State.Flat.ScopeProvider;
+using Nethermind.Trie;
+using Nethermind.Trie.Pruning;
+using Prometheus;
+
+namespace Nethermind.State.Flat;
+
+public class FlatDiffRepository : IFlatDiffRepository, IAsyncDisposable
+{
+ private ReaderWriterLockSlim _repoLock = new ReaderWriterLockSlim(); // Note: lock is for proteccting in memory and compacted states only
+ private readonly ICanonicalStateRootFinder _stateRootFinder;
+ private Dictionary _compactedKnownStates = new();
+ private InMemorySnapshotStore _inMemorySnapshotStore;
+ private ResourcePool _resourcePool;
+ private List<(Hash256AsKey, TreePath)> _trieNodesSortBuffer = new List<(Hash256AsKey, TreePath)>(); // Presort make it faster
+ private readonly Task _compactorTask;
+
+ private Lock _readerCacheLock = new Lock();
+ private RefCountingPersistenceReader? _cachedReader = null;
+ private readonly TrieNodeCache _trieNodeCache;
+ private readonly Task _persistenceTask;
+
+ private IPersistence _persistence;
+ private int _boundary;
+
+ private Channel<(StateId, CachedResource)> _compactorJobs;
+ private Channel _persistenceJob;
+ private long _compactSize;
+ private long _compactEveryBlockNum;
+ private readonly bool _inlineCompaction;
+ private ILogger _logger;
+ private StateId _currentPersistedState;
+
+ private static Histogram _flatdiffimes = DevMetric.Factory.CreateHistogram("flatdiff_times", "aha", new HistogramConfiguration()
+ {
+ LabelNames = new[] { "category", "type" },
+ // Buckets = Histogram.PowersOfTenDividedBuckets(2, 12, 5)
+ Buckets = [1]
+ });
+
+ private static Gauge _knownStatesMemory = DevMetric.Factory.CreateGauge("flatdiff_knownstates_memory", "memory", "category");
+ private static Gauge _compactedMemory = DevMetric.Factory.CreateGauge("flatdiff_compacted_memory", "memory", "category");
+
+ public event EventHandler? ReorgBoundaryReached;
+
+ public record Configuration(
+ int MaxInFlightCompactJob = 32,
+ int CompactSize = 64,
+ int CompactInterval = 4,
+ int ConcurrentCompactor = 4,
+ int Boundary = 128,
+ long TrieCacheMemoryTarget = 2_000_000_000,
+ bool VerifyWithTrie = false,
+ bool ReadWithTrie = false,
+ bool InlineCompaction = false,
+ bool DisableTrieWarmer = false
+ )
+ {
+ }
+
+ public FlatDiffRepository(
+ IProcessExitSource exitSource,
+ ICanonicalStateRootFinder stateRootFinder,
+ IPersistence persistedPersistence,
+ ResourcePool resourcePool,
+ ILogManager logManager,
+ Configuration? config = null)
+ {
+ if (config is null) config = new Configuration();
+ _inMemorySnapshotStore = new InMemorySnapshotStore();
+ _persistence = persistedPersistence;
+ _compactSize = config.CompactSize;
+ _compactEveryBlockNum = config.CompactInterval;
+ _inlineCompaction = config.InlineCompaction;
+ _stateRootFinder = stateRootFinder;
+ _resourcePool = resourcePool;
+ _logger = logManager.GetClassLogger();
+
+ _compactorJobs = Channel.CreateBounded<(StateId, CachedResource)>(config.MaxInFlightCompactJob);
+ _persistenceJob = Channel.CreateBounded(config.MaxInFlightCompactJob);
+ _boundary = config.Boundary;
+
+ using var reader = LeaseReader();
+ _currentPersistedState = reader.CurrentState;
+ _trieNodeCache = new TrieNodeCache(config.TrieCacheMemoryTarget, logManager);
+
+ _compactorTask = RunCompactor(exitSource.Token);
+ _persistenceTask = RunPersistence(exitSource.Token);
+ }
+
+
+ public IPersistence.IPersistenceReader LeaseReader()
+ {
+ using var _ = _readerCacheLock.EnterScope();
+ var cachedReader = _cachedReader;
+ if (cachedReader is null)
+ {
+ _cachedReader = cachedReader = new RefCountingPersistenceReader(
+ _persistence.CreateReader(),
+ _logger
+ );
+ }
+
+ cachedReader.AcquireLease();
+ return cachedReader;
+ }
+
+ private void ClearReaderCache()
+ {
+ using var _ = _readerCacheLock.EnterScope();
+ RefCountingPersistenceReader? cachedReader = _cachedReader;
+ _cachedReader = null;
+ cachedReader?.Dispose();
+ }
+
+ private async Task RunCompactor(CancellationToken cancellationToken)
+ {
+ try
+ {
+ await foreach (var (stateId, cachedResource) in _compactorJobs.Reader.ReadAllAsync(cancellationToken))
+ {
+ try
+ {
+ CompactLevel(stateId, cachedResource);
+ if (stateId.blockNumber % _compactSize == 0)
+ {
+ await _persistenceJob.Writer.WriteAsync(stateId, cancellationToken);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("Compact job failed", ex);
+ throw;
+ }
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ }
+
+ private async Task RunPersistence(CancellationToken cancellationToken)
+ {
+ try
+ {
+ await foreach (var _ in _persistenceJob.Reader.ReadAllAsync(cancellationToken))
+ {
+ try
+ {
+ await PersistIfNeeded();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("Persistence job failed", ex);
+ throw;
+ }
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ }
+
+ private async Task NotifyWhenSlow(string name, Action closure)
+ {
+ Task jobTask = Task.Run(() =>
+ {
+ try
+ {
+ closure();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"job {name} failed", ex);
+ Environment.Exit(1);
+ throw;
+ }
+ });
+ Task waiterTask = Task.Run(async () =>
+ {
+ Stopwatch sw = Stopwatch.StartNew();
+ while (true)
+ {
+ await Task.Delay(1000);
+ if (jobTask.IsCompleted) break;
+ _logger.Info($"Task {name} took {sw.Elapsed}");
+ }
+ });
+
+ await Task.WhenAny(jobTask, waiterTask);
+ }
+
+ private void RunCompactJob(StateId stateId, CachedResource cachedResource)
+ {
+ CompactLevel(stateId, cachedResource);
+ PersistIfNeeded().Wait();
+ }
+
+ private RepolockReadExiter EnterRepolockReadOnly()
+ {
+ _repoLock.EnterReadLock();
+
+ return new RepolockReadExiter(_repoLock, true);
+ }
+
+ private RepolockReadExiter EnterRepolock()
+ {
+ _repoLock.EnterWriteLock();
+
+ return new RepolockReadExiter(_repoLock, false);
+ }
+
+ private ref struct RepolockReadExiter(ReaderWriterLockSlim @lock, bool read) : IDisposable
+ {
+ public void Dispose()
+ {
+ if (read)
+ {
+ @lock.ExitReadLock();
+ }
+ else
+ {
+ @lock.ExitWriteLock();
+ }
+ }
+ }
+
+ private void CompactLevel(StateId stateId, CachedResource cachedResource)
+ {
+ try
+ {
+ if (PopulateTrieNodeCache(cachedResource)) return;
+
+ if (_compactSize <= 1) return; // Disabled
+ long blockNumber = stateId.blockNumber;
+ if (blockNumber == 0) return;
+ if (blockNumber % _compactSize != 0)
+ {
+ using (EnterRepolockReadOnly())
+ {
+ StateId? last = _inMemorySnapshotStore.GetLast();
+ if (last != null && last.Value.blockNumber - blockNumber > 1)
+ {
+ // To slow. Just skip this block number.
+ return;
+ }
+ }
+
+ if (blockNumber % _compactEveryBlockNum != 0) return;
+ }
+
+ long startingBlockNumber = ((blockNumber - 1) / _compactSize) * _compactSize;
+
+ using SnapshotBundle gatheredCache = GatherCache(stateId, IFlatDiffRepository.SnapshotBundleUsage.Compactor, startingBlockNumber);
+ if (gatheredCache.SnapshotCount == 1)
+ {
+ return;
+ }
+
+ if (_logger.IsDebug) _logger.Debug($"Compacting {stateId}");
+ long sw = Stopwatch.GetTimestamp();
+ Snapshot snapshot = gatheredCache.CompactToKnownState();
+ _flatdiffimes.WithLabels("compaction", "compact_to_known_state").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ Dictionary memory = snapshot.EstimateMemory();
+
+ using (EnterRepolock())
+ {
+ _flatdiffimes.WithLabels("compaction", "add_repolock").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ if (_logger.IsDebug) _logger.Debug($"Compacted {gatheredCache.SnapshotCount} to {stateId}");
+
+ if (_compactedKnownStates.TryAdd(stateId, snapshot))
+ {
+ foreach (var keyValuePair in memory)
+ {
+ _compactedMemory.WithLabels(keyValuePair.Key.ToString()).Inc(keyValuePair.Value);
+ }
+ _compactedMemory.WithLabels("count").Inc(1);
+ }
+ else
+ {
+ snapshot.Dispose();
+ }
+
+ _flatdiffimes.WithLabels("compaction", "add_and_measure").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ if (stateId.blockNumber % _compactSize != 0)
+ {
+ // Save memory
+ foreach (var id in _inMemorySnapshotStore.GetStatesAtBlockNumber(stateId.blockNumber - _compactSize))
+ {
+ RemoveAndReleaseCompactedKnownState(id);
+ }
+ }
+
+ _flatdiffimes.WithLabels("compaction", "cleanup_compacted").Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.Error($"Compactor failed {e}");
+ }
+ }
+
+ private bool PopulateTrieNodeCache(CachedResource cachedResource)
+ {
+ Snapshot lastSnapshot;
+ using (EnterRepolockReadOnly())
+ {
+ StateId? last = _inMemorySnapshotStore.GetLast();
+ if (last == null) return true;
+ if (!TryLeaseState(last.Value, out lastSnapshot)) return true;
+ }
+
+ try
+ {
+ var memory = lastSnapshot.EstimateMemory(); // Note: This is slow, do it outside.
+ foreach (var keyValuePair in memory)
+ {
+ _knownStatesMemory.WithLabels(keyValuePair.Key.ToString()).Inc(keyValuePair.Value);
+ }
+ _knownStatesMemory.WithLabels("count").Inc(1);
+
+ long sw = Stopwatch.GetTimestamp();
+ _trieNodeCache.Add(lastSnapshot, cachedResource);
+ _flatdiffimes.WithLabels("compaction", "add_to_trienode_cache").Observe(Stopwatch.GetTimestamp() - sw);
+ _resourcePool.ReturnCachedResource(IFlatDiffRepository.SnapshotBundleUsage.MainBlockProcessing, cachedResource);
+ return false;
+ }
+ finally
+ {
+ lastSnapshot.Dispose();
+ }
+ }
+
+ public SnapshotBundle? GatherReaderAtBaseBlock(StateId baseBlock, IFlatDiffRepository.SnapshotBundleUsage usage)
+ {
+ // TODO: Throw if not enough or return null
+ return GatherCache(baseBlock, usage, null);
+ }
+
+ private static Histogram _knownStatesSize = DevMetric.Factory.CreateHistogram("flatdiff_known_state_size", "timer",
+ new HistogramConfiguration()
+ {
+ LabelNames = ["part"],
+ // Buckets = Histogram.LinearBuckets(0, 1, 100)
+ Buckets = [1]
+ });
+
+ private SnapshotBundle GatherCache(StateId baseBlock, IFlatDiffRepository.SnapshotBundleUsage usage, long? earliestExclusive = null) {
+ long sw = Stopwatch.GetTimestamp();
+ using var _ = EnterRepolockReadOnly();
+ _flatdiffimes.WithLabels("gather_cache", "repolock").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ ArrayPoolList knownStates = new(Math.Max(1, (int)(_inMemorySnapshotStore.KnownStatesCount / _compactSize)));
+
+ if (_logger.IsTrace) _logger.Trace($"Gathering {baseBlock}. Earliest is {earliestExclusive}");
+
+ StateId bigCacheState = _currentPersistedState;
+
+ // TODO: Determine if using a linked list of snapshot make more sense. Measure the impact of this loop and the
+ // dispose loop.
+ string exitReason = "";
+ StateId current = baseBlock;
+ while(TryLeaseCompactedState(current, out var entry) || TryLeaseState(current, out entry))
+ {
+ Snapshot state = entry;
+ if (_logger.IsTrace) _logger.Trace($"Got {state.From} -> {state.To}");
+ knownStates.Add(state);
+ if (state.From == current) {
+ exitReason = "cycle";
+ break; // Some test commit two block with the same id, so we dont know the parent anymore.
+ }
+ current = state.From;
+
+ if (state.To.blockNumber <= bigCacheState.blockNumber)
+ {
+ exitReason = $"First {state.From} to {bigCacheState}";
+ break; // Or equal?
+ }
+ if (state.From.blockNumber <= earliestExclusive) break;
+ }
+
+ _flatdiffimes.WithLabels("gather_cache", "gather").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ _knownStatesSize.Observe(knownStates.Count);
+
+ // Note: By the time the previous loop finished checking all state, the big cache may have added new state and removed some
+ // entry in `_inMemorySnapshotStore`. Meaning, this need to be here instead oof before the loop.
+ IPersistence.IPersistenceReader bigCacheReader = LeaseReader();
+ if (current != baseBlock && earliestExclusive is null && bigCacheReader.CurrentState.blockNumber != -1 && current.blockNumber > bigCacheReader.CurrentState.blockNumber)
+ {
+ throw new Exception($"Non consecutive snappshots. Current {current} vs {bigCacheReader.CurrentState}, {bigCacheState}, {baseBlock}, {_inMemorySnapshotStore.TryGetValue(current, out var snapshot)}, {exitReason}");
+ }
+
+ if (bigCacheReader.CurrentState.blockNumber > baseBlock.blockNumber)
+ {
+ _logger.Warn("Big cache too early");
+ bigCacheReader.Dispose();
+ bigCacheReader = new NoopPersistenceReader();
+ }
+
+ // TODO: Measure this
+ knownStates.Reverse();
+ _flatdiffimes.WithLabels("gather_cache", "reverse").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ if (_logger.IsTrace) _logger.Trace($"Gathered {baseBlock}. Earliest is {earliestExclusive}, Got {knownStates.Count} known states, {_currentPersistedState}");
+ var res = new SnapshotBundle(
+ knownStates,
+ bigCacheReader,
+ _trieNodeCache,
+ _resourcePool,
+ usage: usage);
+ _flatdiffimes.WithLabels("gather_cache", "done").Observe(Stopwatch.GetTimestamp() - sw);
+ return res;
+ }
+
+ public bool TryLeaseCompactedState(StateId stateId, out Snapshot entry)
+ {
+ if (!_compactedKnownStates.TryGetValue(stateId, out entry)) return false;
+ if (!entry.TryAcquire()) return false;
+ return true;
+ }
+
+ public bool TryLeaseState(StateId stateId, out Snapshot entry)
+ {
+ if (!_inMemorySnapshotStore.TryGetValue(stateId, out entry)) return false;
+ if (!entry.TryAcquire()) return false;
+ return true;
+ }
+
+ public void AddSnapshot(Snapshot snapshot, CachedResource cachedResource)
+ {
+ long sw = Stopwatch.GetTimestamp();
+
+ StateId startingBlock = snapshot.From;
+ StateId endBlock = snapshot.To;
+ using (EnterRepolock())
+ {
+ _flatdiffimes.WithLabels("add_snapshot", "repolock").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ if (_logger.IsTrace) _logger.Trace($"Registering {startingBlock.blockNumber} to {endBlock.blockNumber}");
+ if (endBlock.blockNumber <= _currentPersistedState.blockNumber)
+ {
+ _logger.Warn(
+ $"Cannot register snapshot earlier than bigcache. Snapshot number {endBlock.blockNumber}, bigcache number: {_currentPersistedState}");
+ return;
+ }
+
+ // snapshot should have 2 lease here
+ _inMemorySnapshotStore.AddBlock(endBlock, snapshot);
+
+ _flatdiffimes.WithLabels("add_snapshot", "add_block").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ }
+
+ if (_inlineCompaction)
+ {
+ RunCompactJob(endBlock, cachedResource);
+ }
+ else
+ {
+ if (!_compactorJobs.Writer.TryWrite((endBlock, cachedResource)))
+ {
+ _flatdiffimes.WithLabels("add_snapshot", "try_write_failed").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ _logger.Warn("Compactor job stall!");
+ _compactorJobs.Writer.WriteAsync((endBlock, cachedResource)).AsTask().Wait();
+ _flatdiffimes.WithLabels("add_snapshot", "write_async").Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _flatdiffimes.WithLabels("add_snapshot", "try_write_ok").Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ }
+ }
+
+ private async Task PersistIfNeeded()
+ {
+ await NotifyWhenSlow("add to bigcache", () => AddToPersistence());
+ }
+
+ private void AddToPersistence()
+ {
+ // Attempt to add snapshots into bigcache
+ while (true)
+ {
+ Snapshot pickedState;
+ StateId? pickedSnapshot = null;
+ List toRemoveStates = new List();
+ long sw = Stopwatch.GetTimestamp();
+ using (EnterRepolock())
+ {
+ _flatdiffimes.WithLabels("add_to_persistence", "repolock").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ long lastSnapshotNumber = _inMemorySnapshotStore.GetLast()?.blockNumber ?? 0;
+ StateId currentState = _currentPersistedState;
+ if (lastSnapshotNumber - currentState.blockNumber <= (_boundary + _compactSize))
+ {
+ break;
+ }
+
+ List candidateToAdd = new List();
+
+ long? blockNumber = null;
+ bool persistCompactedStates = false;
+ // Note: Need to verify that this is finalized
+ foreach (var stateId in _inMemorySnapshotStore.GetStatesAfterBlock(currentState.blockNumber + _compactSize - 1))
+ {
+ if (stateId.blockNumber > currentState.blockNumber + _compactSize)
+ {
+ break;
+ }
+ if (_compactedKnownStates.TryGetValue(stateId, out var existingState))
+ {
+ if (blockNumber is null)
+ {
+ if (existingState.From != currentState)
+ {
+ if (_logger.IsDebug) _logger.Debug($"Not using compacted state. Mismatch. {existingState.From}, query {stateId} vs {currentState}");
+ break;
+ }
+
+ if (_logger.IsDebug) _logger.Debug($"Setting compacted state");
+ persistCompactedStates = true;
+ blockNumber = stateId.blockNumber;
+ candidateToAdd.Add(stateId);
+ }
+ else if (blockNumber == stateId.blockNumber)
+ {
+ candidateToAdd.Add(stateId);
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ if (_logger.IsDebug) _logger.Debug($"Cancelling setting compacted state, {stateId}");
+ persistCompactedStates = false;
+ candidateToAdd.Clear();
+ blockNumber = null;
+ break;
+ }
+ }
+
+ if (persistCompactedStates)
+ {
+ if (_logger.IsDebug) _logger.Debug($"Using compacted state. {blockNumber}, vs {currentState}");
+ }
+
+ if (blockNumber is null)
+ {
+ foreach (var stateId in _inMemorySnapshotStore.GetStatesAfterBlock(currentState.blockNumber))
+ {
+ if (blockNumber is null)
+ {
+ blockNumber = stateId.blockNumber;
+ candidateToAdd.Add(stateId);
+ }
+ else if (blockNumber == stateId.blockNumber)
+ {
+ candidateToAdd.Add(stateId);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ Debug.Assert(candidateToAdd.Count > 0);
+
+ if (candidateToAdd.Count > 1)
+ {
+ Hash256? canonicalStateRoot = _stateRootFinder.GetCanonicalStateRootAtBlock(blockNumber.Value);
+ if (canonicalStateRoot is null)
+ {
+ _logger.Warn($"Canonical state root for block {blockNumber} not known");
+ return;
+ }
+
+ foreach (var stateId in candidateToAdd)
+ {
+ if (stateId.stateRoot == canonicalStateRoot)
+ {
+ pickedSnapshot = stateId;
+ }
+ }
+ }
+ else
+ {
+ pickedSnapshot = candidateToAdd[0];
+ }
+
+ if (!pickedSnapshot.HasValue)
+ {
+ // Ah, probably filter the compacted state here instead
+ _logger.Warn($"Unable to determine canonicaal snapshot");
+ return;
+ }
+
+ // Remove non-canon snapshots
+ foreach (var stateId in candidateToAdd)
+ {
+ if (stateId != pickedSnapshot)
+ {
+ RemoveAndReleaseCompactedKnownState(stateId);
+ RemoveAndReleaseKnownState(stateId);
+ }
+ }
+
+ if (persistCompactedStates)
+ {
+ _compactedKnownStates.TryGetValue(pickedSnapshot.Value, out pickedState);
+ pickedState.AcquireLease();
+ if (_logger.IsDebug) _logger.Debug($"Picking compacted state {pickedState.From} to {pickedState.To}");
+
+ foreach (var stateId in _inMemorySnapshotStore.GetStatesAfterBlock(currentState.blockNumber))
+ {
+ if (stateId.blockNumber < pickedSnapshot.Value.blockNumber)
+ {
+ toRemoveStates.Add(stateId);
+ }
+ }
+ }
+ else
+ {
+ _inMemorySnapshotStore.TryGetValue(pickedSnapshot.Value, out pickedState);
+ pickedState.AcquireLease();
+ }
+ }
+ _flatdiffimes.WithLabels("add_to_persistence", "state_picked").Observe(Stopwatch.GetTimestamp() - sw);
+
+ // Add the canon snapshot
+ Add(pickedState);
+ pickedState.Dispose();
+
+ sw = Stopwatch.GetTimestamp();
+ // And we remove it
+ using (EnterRepolock())
+ {
+ RemoveAndReleaseCompactedKnownState(pickedSnapshot.Value);
+ RemoveAndReleaseKnownState(pickedSnapshot.Value);
+
+ foreach (var stateId in toRemoveStates)
+ {
+ RemoveAndReleaseCompactedKnownState(stateId);
+ RemoveAndReleaseKnownState(stateId);
+ }
+ }
+ _flatdiffimes.WithLabels("add_to_persistence", "cleanup").Observe(Stopwatch.GetTimestamp() - sw);
+
+ sw = Stopwatch.GetTimestamp();
+
+ ReorgBoundaryReached?.Invoke(this, new ReorgBoundaryReached(pickedSnapshot.Value.blockNumber));
+
+ _flatdiffimes.WithLabels("add_to_persistence", "reorg_boundary").Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ }
+
+ private void RemoveAndReleaseCompactedKnownState(StateId stateId)
+ {
+ if (_compactedKnownStates.Remove(stateId, out var existingState))
+ {
+ var memory = existingState.EstimateMemory();
+ foreach (var keyValuePair in memory)
+ {
+ _compactedMemory.WithLabels(keyValuePair.Key.ToString()).Dec(keyValuePair.Value);
+ }
+ _compactedMemory.WithLabels("count").Dec(1);
+
+ existingState.Dispose();
+ }
+ }
+
+ private void RemoveAndReleaseKnownState(StateId stateId)
+ {
+ if (!_repoLock.IsWriteLockHeld) throw new InvalidOperationException("Must hold write lock to repolock to change snapshot store");
+ if (_inMemorySnapshotStore.TryGetValue(stateId, out var existingState))
+ {
+ _inMemorySnapshotStore.Remove(stateId);
+ var memory = existingState.EstimateMemory();
+ foreach (var keyValuePair in memory)
+ {
+ _knownStatesMemory.WithLabels(keyValuePair.Key.ToString()).Dec(keyValuePair.Value);
+ }
+ _knownStatesMemory.WithLabels("count").Dec();
+
+ existingState.Dispose(); // After memory
+ }
+ }
+
+ public void Add(Snapshot snapshot)
+ {
+ if (snapshot.To.blockNumber - snapshot.From.blockNumber != _compactSize) _logger.Warn($"Snapshot size write is {snapshot.To.blockNumber - snapshot.From.blockNumber}");
+ long sw = Stopwatch.GetTimestamp();
+ using (var batch = _persistence.CreateWriteBatch(snapshot.From, snapshot.To))
+ {
+ _flatdiffimes.WithLabels("persistence", "start_batch").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ int counter = 0;
+ foreach (var toSelfDestructStorage in snapshot.SelfDestructedStorageAddresses)
+ {
+ if (toSelfDestructStorage.Value)
+ {
+ /*
+ int deleted = batch.SelfDestruct(toSelfDestructStorage.Key.Value);
+ if (toSelfDestructStorage.Key.Value == FlatWorldStateScope.DebugAddress)
+ {
+ Console.Error.WriteLine($"Selfdestruct should skip {toSelfDestructStorage.Key}");
+ }
+ if (deleted > 0)
+ {
+ _logger.Warn($"Should selfdestruct {toSelfDestructStorage.Key}. Deleted {deleted}. Snapshot range {snapshot.From} {snapshot.To}");
+ throw new Exception($"Should sefl destruct not called properly {toSelfDestructStorage.Key}");
+ }
+ */
+ continue;
+ }
+
+ int num = batch.SelfDestruct(toSelfDestructStorage.Key.Value);
+ if (toSelfDestructStorage.Key.Value == FlatWorldStateScope.DebugAddress)
+ {
+ using var r = LeaseReader();
+ bool _ = r.TryGetSlot(FlatWorldStateScope.DebugAddress, FlatWorldStateScope.DebugSlot, out var value);
+ Console.Error.WriteLine($"Selfdestructed {toSelfDestructStorage.Key} {num}, {value?.ToHexString()}");
+ }
+ counter++;
+ }
+ _flatdiffimes.WithLabels("persistence", "self_destruct").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ foreach (var kv in snapshot.Accounts)
+ {
+ (Address addr, Account? account) = kv;
+ if (account is null)
+ batch.RemoveAccount(addr);
+ else
+ batch.SetAccount(addr, account);
+ }
+ _flatdiffimes.WithLabels("persistence", "accounts").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ foreach (var kv in snapshot.Storages)
+ {
+ ((Address addr, UInt256 slot), byte[] value) = kv;
+
+ if (value is null || Bytes.AreEqual(value, StorageTree.ZeroBytes))
+ {
+ batch.RemoveStorage(addr, slot);
+ }
+ else
+ {
+ batch.SetStorage(addr, slot, value);
+ }
+ }
+ _flatdiffimes.WithLabels("persistence", "storages").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ _trieNodesSortBuffer.Clear();
+ _trieNodesSortBuffer.AddRange(snapshot.StateNodeKeys.Select((path) => (null, path)));
+ _trieNodesSortBuffer.Sort();
+ _flatdiffimes.WithLabels("persistence", "trienode_sort_state").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ // foreach (var tn in snapshot.TrieNodes)
+ foreach (var k in _trieNodesSortBuffer)
+ {
+ (_, TreePath path) = k;
+
+ snapshot.TryGetStateNode(path, out TrieNode node);
+
+ if (node.FullRlp.Length == 0)
+ {
+ // TODO: Need to double check this case. Does it need a rewrite or not?
+ if (node.NodeType == NodeType.Unknown)
+ {
+ continue;
+ }
+ }
+
+ // Note: Even if the node already marked as persisted, we still re-persist it
+ batch.SetTrieNodes(null, path, node);
+
+ node.IsPersisted = true;
+ }
+ _flatdiffimes.WithLabels("persistence", "trienodes").Observe(Stopwatch.GetTimestamp() - sw);
+
+ _trieNodesSortBuffer.Clear();
+ _trieNodesSortBuffer.AddRange(snapshot.StorageTrieNodeKeys);
+ _trieNodesSortBuffer.Sort();
+ _flatdiffimes.WithLabels("persistence", "trienode_sort").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+
+ // foreach (var tn in snapshot.TrieNodes)
+ foreach (var k in _trieNodesSortBuffer)
+ {
+ (Hash256AsKey address, TreePath path) = k;
+
+ snapshot.TryGetStorageNode(address, path, out TrieNode node);
+
+ if (node.FullRlp.Length == 0)
+ {
+ // TODO: Need to double check this case. Does it need a rewrite or not?
+ if (node.NodeType == NodeType.Unknown)
+ {
+ continue;
+ }
+ }
+
+ // Note: Even if the node already marked as persisted, we still re-persist it
+ batch.SetTrieNodes(address, path, node);
+
+ node.IsPersisted = true;
+ }
+ _flatdiffimes.WithLabels("persistence", "trienodes").Observe(Stopwatch.GetTimestamp() - sw);
+
+ sw = Stopwatch.GetTimestamp();
+ }
+ _flatdiffimes.WithLabels("persistence", "dispose").Observe(Stopwatch.GetTimestamp() - sw);
+
+ _currentPersistedState = snapshot.To;
+ ClearReaderCache();
+ }
+
+
+ public void FlushCache(CancellationToken cancellationToken)
+ {
+ Console.Error.WriteLine("Flush cache not implemented");
+ }
+
+ public bool HasStateForBlock(StateId stateId)
+ {
+ if (_inMemorySnapshotStore.TryGetValue(stateId, out var snapshot))
+ {
+ return true;
+ }
+
+ if (_currentPersistedState == stateId) return true;
+ return false;
+ }
+
+ public StateId? FindStateIdForStateRoot(Hash256 stateRoot)
+ {
+ using (EnterRepolockReadOnly())
+ {
+ foreach (var stateId in _inMemorySnapshotStore.GetKeysBetween(new StateId(0, Hash256.Zero), new StateId(long.MaxValue, Keccak.MaxValue)))
+ {
+ if (stateId.stateRoot == stateRoot) return stateId;
+ }
+
+ if (_currentPersistedState.stateRoot == stateRoot)
+ {
+ return _currentPersistedState;
+ }
+ }
+
+ return null;
+ }
+
+ public StateId? FindLatestAvailableState()
+ {
+ using (EnterRepolockReadOnly())
+ {
+ StateId? lastInMemory = _inMemorySnapshotStore.GetLast();
+ if (lastInMemory != null) return lastInMemory;
+
+ return _currentPersistedState;
+ }
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ await _compactorTask;
+ await _persistenceTask;
+ ClearReaderCache();
+
+ return;
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/FlatStateReader.cs b/src/Nethermind/Nethermind.State/Flat/FlatStateReader.cs
new file mode 100644
index 00000000000..e2f15e4015e
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/FlatStateReader.cs
@@ -0,0 +1,94 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Autofac.Features.AttributeFilters;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Utils;
+using Nethermind.Db;
+using Nethermind.Int256;
+using Nethermind.Logging;
+using Nethermind.State.Flat.ScopeProvider;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat;
+
+public class FlatStateReader(
+ [KeyFilter(DbNames.Code)] IDb codeDb,
+ ReadonlyReaderRepository readonlyReaderRepositor,
+ IFlatDiffRepository flatDiffRepository,
+ ILogManager logManager
+): IStateReader
+{
+ public bool TryGetAccount(BlockHeader? baseBlock, Address address, out AccountStruct account)
+ {
+ using RefCountingDisposableBox readerBox = readonlyReaderRepositor.GatherReadOnlyReaderAtBaseBlock(new StateId(baseBlock));
+ if (readerBox is null)
+ {
+ account = default;
+ return false;
+ }
+
+ SnapshotBundle reader = readerBox.Item;
+ if (reader.TryGetAccount(address, out Account? accountCls) && accountCls != null)
+ {
+ account = accountCls.ToStruct();
+ return true;
+ }
+
+ account = default;
+ return false;
+ }
+
+ // TODO: Why is it return span? How is it suppose to dispose itself?
+ public ReadOnlySpan GetStorage(BlockHeader? baseBlock, Address address, in UInt256 index)
+ {
+ using RefCountingDisposableBox readerBox = readonlyReaderRepositor.GatherReadOnlyReaderAtBaseBlock(new StateId(baseBlock));
+ if (readerBox is null)
+ {
+ return Array.Empty();
+ }
+
+ SnapshotBundle reader = readerBox.Item;
+ if (reader.TryGetSlot(address, index, reader.DetermineSelfDestructSnapshotIdx(address), out byte[] value))
+ {
+ return value;
+ }
+
+ return Array.Empty();
+ }
+
+ public byte[]? GetCode(Hash256 codeHash) => codeHash == Keccak.OfAnEmptyString ? [] : codeDb[codeHash.Bytes];
+
+ public byte[]? GetCode(in ValueHash256 codeHash) => codeHash == Keccak.OfAnEmptyString.ValueHash256 ? [] : codeDb[codeHash.Bytes];
+
+ public void RunTreeVisitor(ITreeVisitor treeVisitor, Hash256 stateRoot, VisitingOptions? visitingOptions = null) where TCtx : struct, INodeContext
+ {
+ StateId? stateId = flatDiffRepository.FindStateIdForStateRoot(stateRoot);
+ if (stateId is null)
+ {
+ throw new InvalidOperationException($"State root {stateRoot} not found");
+ }
+
+ using RefCountingDisposableBox readerBox = readonlyReaderRepositor.GatherReadOnlyReaderAtBaseBlock(stateId.Value);
+ if (readerBox is null)
+ {
+ throw new InvalidOperationException($"State root {stateRoot} not found");
+ }
+
+ SnapshotBundle reader = readerBox.Item;
+ StateTrieStoreAdapter trieStoreAdapter = new StateTrieStoreAdapter(
+ reader,
+ new ConcurrencyQuota(),
+ false);
+
+ PatriciaTree patriciaTree = new PatriciaTree(trieStoreAdapter, logManager);
+ patriciaTree.Accept(treeVisitor, stateRoot, visitingOptions);
+ }
+
+ public bool HasStateForBlock(BlockHeader? baseBlock)
+ {
+ return flatDiffRepository.HasStateForBlock(new StateId(baseBlock));
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/FlatVerifyTrieVisitor.cs b/src/Nethermind/Nethermind.State/Flat/FlatVerifyTrieVisitor.cs
new file mode 100644
index 00000000000..4d1d36617af
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/FlatVerifyTrieVisitor.cs
@@ -0,0 +1,338 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Text;
+using System.Threading;
+using Nethermind.Core;
+using Nethermind.Core.Caching;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Logging;
+using Nethermind.Serialization.Rlp;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat;
+
+public class FlatVerifyTrieVisitor : ITreeVisitor
+{
+ private readonly ClockCache _existingCodeHash = new ClockCache(1024 * 8);
+ private readonly IKeyValueStore _codeKeyValueStore;
+ private long _lastAccountNodeCount = 0;
+
+ private readonly ILogger _logger;
+ private readonly CancellationToken _cancellationToken;
+ private readonly IPersistence.IPersistenceReader _persistenceReader;
+
+ // Combine both `TreePathContextWithStorage` and `OldStyleTrieVisitContext`
+ public struct Context : INodeContext
+ {
+ private TreePathContextWithStorage PathContext;
+ private OldStyleTrieVisitContext OldStyleTrieVisitContext;
+
+ public readonly Hash256? Storage => PathContext.Storage;
+ public readonly TreePath Path => PathContext.Path;
+ public readonly bool IsStorage => OldStyleTrieVisitContext.IsStorage;
+ public readonly int Level => OldStyleTrieVisitContext.Level;
+
+ public readonly Context Add(ReadOnlySpan nibblePath)
+ {
+ return new Context()
+ {
+ PathContext = PathContext.Add(nibblePath),
+ OldStyleTrieVisitContext = OldStyleTrieVisitContext.Add(nibblePath)
+ };
+ }
+
+ public readonly Context Add(byte nibble)
+ {
+ return new Context()
+ {
+ PathContext = PathContext.Add(nibble),
+ OldStyleTrieVisitContext = OldStyleTrieVisitContext.Add(nibble)
+ };
+ }
+
+ public readonly Context AddStorage(in ValueHash256 storage)
+ {
+ return new Context()
+ {
+ PathContext = PathContext.AddStorage(storage),
+ OldStyleTrieVisitContext = OldStyleTrieVisitContext.AddStorage(storage)
+ };
+ }
+ }
+
+ public bool ExpectAccounts { get; }
+
+ public FlatVerifyTrieVisitor(
+ IKeyValueStore codeKeyValueStore,
+ IPersistence.IPersistenceReader persistenceReader,
+ ILogManager logManager,
+ CancellationToken cancellationToken = default,
+ bool expectAccounts = true)
+ {
+ _persistenceReader = persistenceReader;
+ _codeKeyValueStore = codeKeyValueStore ?? throw new ArgumentNullException(nameof(codeKeyValueStore));
+ _logger = logManager.GetClassLogger();
+ ExpectAccounts = expectAccounts;
+ _cancellationToken = cancellationToken;
+ }
+
+ public TrieStats Stats { get; } = new();
+
+ public bool IsFullDbScan => true;
+ public void VisitTree(in Context nodeContext, in ValueHash256 rootHash)
+ {
+ }
+
+ public bool ShouldVisit(in Context nodeContext, in ValueHash256 nextNode)
+ {
+ return true;
+ }
+
+ public void VisitMissingNode(in Context nodeContext, in ValueHash256 nodeHash)
+ {
+ if (nodeContext.IsStorage)
+ {
+ if (_logger.IsWarn) _logger.Warn($"Missing node. Storage: {nodeContext.Storage} Path: {nodeContext.Path} Hash: {nodeHash}");
+ Interlocked.Increment(ref Stats._missingStorage);
+ }
+ else
+ {
+ if (_logger.IsWarn) _logger.Warn($"Missing node. Path: {nodeContext.Path} Hash: {nodeHash}");
+ Interlocked.Increment(ref Stats._missingState);
+ }
+
+ IncrementLevel(nodeContext);
+ }
+
+ public void VisitBranch(in Context nodeContext, TrieNode node)
+ {
+ _cancellationToken.ThrowIfCancellationRequested();
+
+ if (nodeContext.IsStorage)
+ {
+ Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length);
+ Interlocked.Increment(ref Stats._storageBranchCount);
+ }
+ else
+ {
+ Interlocked.Add(ref Stats._stateSize, node.FullRlp.Length);
+ Interlocked.Increment(ref Stats._stateBranchCount);
+ }
+
+ IncrementLevel(nodeContext);
+ }
+
+ public void VisitExtension(in Context nodeContext, TrieNode node)
+ {
+ if (nodeContext.IsStorage)
+ {
+ Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length);
+ Interlocked.Increment(ref Stats._storageExtensionCount);
+ }
+ else
+ {
+ Interlocked.Add(ref Stats._stateSize, node.FullRlp.Length);
+ Interlocked.Increment(ref Stats._stateExtensionCount);
+ }
+
+ IncrementLevel(nodeContext);
+ }
+
+ public void VisitLeaf(in Context nodeContext, TrieNode node)
+ {
+ long lastAccountNodeCount = _lastAccountNodeCount;
+ long currentNodeCount = Stats.NodesCount;
+ if (currentNodeCount - lastAccountNodeCount > 1_000_000 && Interlocked.CompareExchange(ref _lastAccountNodeCount, currentNodeCount, lastAccountNodeCount) == lastAccountNodeCount)
+ {
+ _logger.Warn($"Collected info from {Stats.NodesCount} nodes. Missing CODE {Stats.MissingCode} STATE {Stats.MissingState} STORAGE {Stats.MissingStorage}");
+ }
+
+ if (nodeContext.IsStorage)
+ {
+ Interlocked.Add(ref Stats._storageSize, node.FullRlp.Length);
+ Interlocked.Increment(ref Stats._storageLeafCount);
+
+ Hash256 fullPath = nodeContext.Path.Append(node.Key).Path.ToHash256();
+ byte[]? nodeSlot = State.StorageTree.ZeroBytes;
+ if (node.Value.IsNotNull)
+ {
+ Rlp.ValueDecoderContext ctx = node.Value.Span.AsRlpValueContext();
+ nodeSlot = ctx.DecodeByteArray();
+ }
+
+ byte[]? flatSlot = _persistenceReader.GetStorageRaw(nodeContext.Storage, fullPath);
+ if (!Bytes.AreEqual(flatSlot, nodeSlot))
+ {
+ if (_logger.IsWarn) _logger.Warn($"Mismatched slot. AddressHash: {nodeContext.Storage}. SlotHash {fullPath}. Trie slot: {nodeSlot.ToHexString() ?? ""}, Flat slot; {flatSlot?.ToHexString()}");
+ Interlocked.Increment(ref Stats._mismatchedSlot);
+ }
+
+ }
+ else
+ {
+ Interlocked.Add(ref Stats._stateSize, node.FullRlp.Length);
+ Interlocked.Increment(ref Stats._accountCount);
+
+ Hash256 addrHash = nodeContext.Path.Append(node.Key).Path.ToHash256();
+ byte[]? rawAccountBytes = _persistenceReader.GetAccountRaw(addrHash);
+ Rlp.ValueDecoderContext ctx = new Rlp.ValueDecoderContext(rawAccountBytes);
+ Account? flatAccount = AccountDecoder.Instance.Decode(ref ctx);
+
+ ctx = node.Value.Span.AsRlpValueContext();
+ Account? nodeAccount = AccountDecoder.Instance.Decode(ref ctx);
+
+ if (nodeAccount != flatAccount)
+ {
+ if (_logger.IsWarn) _logger.Warn($"Mismatched account. AddressHash: {addrHash}. Trie account: {nodeAccount}, Flat account; {flatAccount}");
+ Interlocked.Increment(ref Stats._mismatchedAccount);
+ }
+ }
+
+ IncrementLevel(nodeContext);
+ }
+
+ public void VisitAccount(in Context nodeContext, TrieNode node, in AccountStruct account)
+ {
+ if (!account.HasCode) return;
+ ValueHash256 key = account.CodeHash;
+ bool codeExist = _existingCodeHash.TryGet(key, out int codeLength);
+ if (!codeExist)
+ {
+ byte[] code = _codeKeyValueStore[key.Bytes];
+ codeExist = code is not null;
+ if (codeExist)
+ {
+ codeLength = code.Length;
+ _existingCodeHash.Set(key, codeLength);
+ }
+ }
+
+ if (codeExist)
+ {
+ Interlocked.Add(ref Stats._codeSize, codeLength);
+ Interlocked.Increment(ref Stats._codeCount);
+ }
+ else
+ {
+ if (_logger.IsWarn) _logger.Warn($"Missing code. Hash: {account.CodeHash}");
+ Interlocked.Increment(ref Stats._missingCode);
+ }
+
+ IncrementLevel(nodeContext, Stats._codeLevels);
+ }
+
+ private void IncrementLevel(Context context)
+ {
+ long[] levels = context.IsStorage ? Stats._storageLevels : Stats._stateLevels;
+ IncrementLevel(context, levels);
+ }
+
+ private static void IncrementLevel(Context context, long[] levels)
+ {
+ Interlocked.Increment(ref levels[context.Level]);
+ }
+
+ public class TrieStats
+ {
+ private const int Levels = 128;
+ internal long _stateBranchCount;
+ internal long _stateExtensionCount;
+ internal long _accountCount;
+ internal long _storageBranchCount;
+ internal long _storageExtensionCount;
+ internal long _storageLeafCount;
+ internal long _codeCount;
+ internal long _missingState;
+ internal long _missingCode;
+ internal long _missingStorage;
+ internal long _mismatchedAccount;
+ internal long _mismatchedSlot;
+ internal long _storageSize;
+ internal long _codeSize;
+ internal long _stateSize;
+ internal readonly long[] _stateLevels = new long[Levels];
+ internal readonly long[] _storageLevels = new long[Levels];
+ internal readonly long[] _codeLevels = new long[Levels];
+
+ public long StateBranchCount => _stateBranchCount;
+
+ public long StateExtensionCount => _stateExtensionCount;
+
+ public long AccountCount => _accountCount;
+
+ public long StorageBranchCount => _storageBranchCount;
+
+ public long StorageExtensionCount => _storageExtensionCount;
+
+ public long StorageLeafCount => _storageLeafCount;
+
+ public long CodeCount => _codeCount;
+
+ public long MissingState => _missingState;
+
+ public long MissingCode => _missingCode;
+
+ public long MissingStorage => _missingStorage;
+
+ public long MismatchedSlot => _mismatchedSlot;
+
+ public long MismatchedAccount => _mismatchedAccount;
+
+ public long MissingNodes => MissingCode + MissingState + MissingStorage;
+
+ public long StorageCount => StorageLeafCount + StorageExtensionCount + StorageBranchCount;
+
+ public long StateCount => AccountCount + StateExtensionCount + StateBranchCount;
+
+ public long NodesCount => StorageCount + StateCount + CodeCount;
+
+ public long StorageSize => _storageSize;
+
+ public long CodeSize => _codeSize;
+
+ public long StateSize => _stateSize;
+
+ public long Size => StateSize + StorageSize + CodeSize;
+
+ // public List MissingNodes { get; set; } = new List();
+
+ public long[] StateLevels => _stateLevels;
+ public long[] StorageLevels => _storageLevels;
+ public long[] CodeLevels => _codeLevels;
+ public long[] AllLevels
+ {
+ get
+ {
+ long[] result = new long[Levels];
+ for (int i = 0; i < result.Length; i++)
+ {
+ result[i] = _stateLevels[i] + _storageLevels[i] + _codeLevels[i];
+ }
+
+ return result;
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder builder = new();
+ builder.AppendLine("TRIE STATS");
+ builder.AppendLine($" SIZE {Size} (STATE {StateSize}, CODE {CodeSize}, STORAGE {StorageSize})");
+ builder.AppendLine($" ALL NODES {NodesCount} ({StateBranchCount + StorageBranchCount}|{StateExtensionCount + StorageExtensionCount}|{AccountCount + StorageLeafCount})");
+ builder.AppendLine($" STATE NODES {StateCount} ({StateBranchCount}|{StateExtensionCount}|{AccountCount})");
+ builder.AppendLine($" STORAGE NODES {StorageCount} ({StorageBranchCount}|{StorageExtensionCount}|{StorageLeafCount})");
+ builder.AppendLine($" ACCOUNTS {AccountCount} OF WHICH ({CodeCount}) ARE CONTRACTS");
+ builder.AppendLine($" MISSING {MissingNodes} (STATE {MissingState}, CODE {MissingCode}, STORAGE {MissingStorage})");
+ builder.AppendLine($" MISMATCHED (ACCOUNT {MismatchedAccount}) (SLOT {MismatchedSlot})");
+ builder.AppendLine($" ALL LEVELS {string.Join(" | ", AllLevels)}");
+ builder.AppendLine($" STATE LEVELS {string.Join(" | ", StateLevels)}");
+ builder.AppendLine($" STORAGE LEVELS {string.Join(" | ", StorageLevels)}");
+ builder.AppendLine($" CODE LEVELS {string.Join(" | ", CodeLevels)}");
+ return builder.ToString();
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ICanonicalStateRootFinder.cs b/src/Nethermind/Nethermind.State/Flat/ICanonicalStateRootFinder.cs
new file mode 100644
index 00000000000..5226ebc5cbd
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ICanonicalStateRootFinder.cs
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Core.Crypto;
+
+namespace Nethermind.State.Flat;
+
+public interface ICanonicalStateRootFinder
+{
+ public Hash256? GetCanonicalStateRootAtBlock(long blockNumber);
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/IFlatDiffRepository.cs b/src/Nethermind/Nethermind.State/Flat/IFlatDiffRepository.cs
new file mode 100644
index 00000000000..58ea35df523
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/IFlatDiffRepository.cs
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Threading;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Utils;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.Trie.Pruning;
+
+namespace Nethermind.State.Flat;
+
+public interface IFlatDiffRepository
+{
+ event EventHandler? ReorgBoundaryReached;
+ SnapshotBundle? GatherReaderAtBaseBlock(StateId baseBlock, SnapshotBundleUsage usage);
+ void AddSnapshot(Snapshot snapshot, CachedResource cachedResource);
+ void FlushCache(CancellationToken cancellationToken);
+ bool HasStateForBlock(StateId stateId);
+ StateId? FindStateIdForStateRoot(Hash256 stateRoot); // Ugh...
+ StateId? FindLatestAvailableState();
+ IPersistence.IPersistenceReader LeaseReader();
+
+ enum SnapshotBundleUsage
+ {
+ MainBlockProcessing,
+ StateReader,
+ ReadOnlyProcessingEnv,
+ Compactor,
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Importer/Importer.cs b/src/Nethermind/Nethermind.State/Flat/Importer/Importer.cs
new file mode 100644
index 00000000000..8175b51e8a8
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/Importer/Importer.cs
@@ -0,0 +1,164 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Threading.Channels;
+using System.Threading.Tasks;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Logging;
+using Nethermind.Serialization.Rlp;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.Trie;
+using Nethermind.Trie.Pruning;
+
+namespace Nethermind.State.Flat.Importer;
+
+public class Importer(
+ INodeStorage nodeStorage,
+ IPersistence persistence,
+ ILogManager logManager
+)
+{
+ ILogger _logger = logManager.GetClassLogger();
+ internal AccountDecoder _accountDecoder = AccountDecoder.Instance;
+
+ private record Entry(Hash256? address, TreePath path, TrieNode node);
+
+ public void Copy(StateId to)
+ {
+ StateId from = new StateId();
+ using (var reader = persistence.CreateReader())
+ {
+ from = reader.CurrentState;
+ }
+
+ ITrieStore trieStore = new RawTrieStore(nodeStorage);
+ PatriciaTree tree = new PatriciaTree(trieStore, logManager);
+ tree.RootHash = to.stateRoot.ToHash256();
+
+ Channel channel = Channel.CreateBounded(1_000_000);
+
+ Task visitTask = Task.Run(() =>
+ {
+ try
+ {
+ tree.Accept(new Visitor(channel.Writer), to.stateRoot.ToHash256(), new VisitingOptions()
+ {
+ MaxDegreeOfParallelism = 1 // The writer is single threaded. Its better to write sorted then.
+ });
+ }
+ finally
+ {
+ channel.Writer.Complete();
+ }
+ });
+
+ Task ingestTask = Task.Run(async () =>
+ {
+ long totalNodes = 0;
+ int batchSize = 4_000_000;
+ int currentBatchSize = 0;
+
+ StateId lastState = from;
+ var writeBatch = persistence.CreateWriteBatch(lastState, to);
+ await foreach (var entry in channel.Reader.ReadAllAsync())
+ {
+ // Write it
+
+ TrieNode node = entry.node;
+ writeBatch.SetTrieNodes(entry.address, entry.path, node);
+ if (node.IsLeaf)
+ {
+ ValueHash256 fullPath = entry.path.Append(node.Key).Path;
+ if (entry.address is null)
+ {
+ Account acc = _accountDecoder.Decode(node.Value.Span);
+ writeBatch.SetAccountRaw(fullPath.ToHash256(), acc);
+ }
+ else
+ {
+
+ ReadOnlySpan value = node.Value.Span;
+ byte[] toWrite;
+
+ if (value.IsEmpty)
+ {
+ toWrite = StorageTree.ZeroBytes;
+ }
+ else
+ {
+ Rlp.ValueDecoderContext rlp = value.AsRlpValueContext();
+ toWrite = rlp.DecodeByteArray();
+ }
+
+ writeBatch.SetStorageRaw(entry.address, fullPath.ToHash256(), toWrite);
+ }
+ }
+
+ currentBatchSize += 1;
+ totalNodes += 1;
+ if (currentBatchSize >= batchSize)
+ {
+ _logger.Info($"Wrote {totalNodes:N} nodes.");
+ writeBatch.Dispose();
+ lastState = to;
+ writeBatch = persistence.CreateWriteBatch(lastState, to);
+ currentBatchSize = 0;
+ }
+ }
+
+ writeBatch.Dispose();
+ _logger.Info($"Flat db copy completed. Wrote {totalNodes} nodes.");
+ });
+
+ Task.WaitAll(ingestTask, visitTask);
+ }
+
+ private class Visitor(ChannelWriter channelWriter) : ITreeVisitor
+ {
+ public bool IsFullDbScan => true;
+ public bool ExpectAccounts => true;
+
+ public bool ShouldVisit(in TreePathContextWithStorage nodeContext, in ValueHash256 nextNode)
+ {
+ return true;
+ }
+
+ public void VisitTree(in TreePathContextWithStorage nodeContext, in ValueHash256 rootHash)
+ {
+ }
+
+ public void VisitMissingNode(in TreePathContextWithStorage nodeContext, in ValueHash256 nodeHash)
+ {
+ throw new Exception("Missing node is not expected");
+ }
+
+ private void Write(in TreePathContextWithStorage nodeContext, TrieNode node)
+ {
+ while (!channelWriter.TryWrite(new Entry(nodeContext.Storage, nodeContext.Path, node)))
+ {
+ channelWriter.WaitToWriteAsync().AsTask().Wait();
+ }
+ }
+
+ public void VisitBranch(in TreePathContextWithStorage nodeContext, TrieNode node)
+ {
+ Write(nodeContext, node);
+ }
+
+ public void VisitExtension(in TreePathContextWithStorage nodeContext, TrieNode node)
+ {
+ Write(nodeContext, node);
+ }
+
+ public void VisitLeaf(in TreePathContextWithStorage nodeContext, TrieNode node)
+ {
+ Write(nodeContext, node);
+ }
+
+ public void VisitAccount(in TreePathContextWithStorage nodeContext, TrieNode node, in AccountStruct account)
+ {
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/InMemorySnapshotStore.cs b/src/Nethermind/Nethermind.State/Flat/InMemorySnapshotStore.cs
new file mode 100644
index 00000000000..8680ce374c4
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/InMemorySnapshotStore.cs
@@ -0,0 +1,69 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Generic;
+using System.Linq;
+using Nethermind.Core.Crypto;
+using Nethermind.State.Flat;
+
+namespace Nethermind.State.Flat;
+
+public class InMemorySnapshotStore
+{
+ private Dictionary _knownStates = new();
+ private SortedSet _sortedKnownStates = new();
+
+ internal int KnownStatesCount => _knownStates.Count;
+
+ public bool TryGetValue(StateId current, out Snapshot value)
+ {
+ return _knownStates.TryGetValue(current, out value);
+ }
+
+ public void AddBlock(StateId endBlock, Snapshot snapshot)
+ {
+ _knownStates[endBlock] = snapshot;
+ _sortedKnownStates.Add(endBlock);
+ }
+
+ public (StateId, Snapshot) GetFirst()
+ {
+ var firstKey = _sortedKnownStates.First();
+ var snapshot = _knownStates[firstKey];
+ return (firstKey, snapshot);
+ }
+
+ public void Remove(StateId firstKey)
+ {
+ _knownStates.Remove(firstKey);
+ _sortedKnownStates.Remove(firstKey);
+ }
+
+ public List GetKeysBetween(StateId start, StateId end)
+ {
+ return _sortedKnownStates.GetViewBetween(start, end).ToList();
+ }
+
+ public List GetStatesAtBlockNumber(long blockNumber)
+ {
+ StateId min = new StateId(blockNumber, ValueKeccak.Zero);
+ StateId max = new StateId(blockNumber, ValueKeccak.MaxValue);
+
+ return GetKeysBetween(min, max).ToList();
+ }
+
+ public IEnumerable GetStatesAfterBlock(long startingBlockNumber)
+ {
+ return GetKeysBetween(
+ new StateId(startingBlockNumber + 1, ValueKeccak.Zero),
+ new StateId(long.MaxValue, ValueKeccak.Zero)
+ );
+ }
+
+ public StateId? GetLast()
+ {
+ if (_sortedKnownStates.Count == 0)
+ return null;
+ return _sortedKnownStates.Last();
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Persistence/IPersistence.cs b/src/Nethermind/Nethermind.State/Flat/Persistence/IPersistence.cs
new file mode 100644
index 00000000000..c4721b79766
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/Persistence/IPersistence.cs
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Int256;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat.Persistence;
+
+public interface IPersistence
+{
+ IPersistenceReader CreateReader();
+ IWriteBatch CreateWriteBatch(StateId from, StateId to);
+
+ public interface IPersistenceReader: IDisposable
+ {
+ bool TryGetAccount(Address address, out Account? acc);
+ bool TryGetSlot(Address address, in UInt256 index, out byte[] value);
+ StateId CurrentState { get; }
+ byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags);
+
+ byte[]? GetAccountRaw(Hash256? addrHash);
+ byte[]? GetStorageRaw(Hash256? addrHash, Hash256 slotHash);
+ }
+
+ public interface IWriteBatch: IDisposable
+ {
+ int SelfDestruct(Address addr);
+ void RemoveAccount(Address addr);
+ void SetAccount(Address addr, Account account);
+ void SetStorage(Address addr, UInt256 slot, ReadOnlySpan value);
+ void SetTrieNodes(Hash256? address, TreePath path, TrieNode tnValue);
+ void RemoveStorage(Address addr, UInt256 slot);
+
+ void SetStorageRaw(Hash256? addrHash, Hash256 slotHash, ReadOnlySpan value);
+ void SetAccountRaw(Hash256? addrHash, Account account);
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Persistence/NoopPersistence.cs b/src/Nethermind/Nethermind.State/Flat/Persistence/NoopPersistence.cs
new file mode 100644
index 00000000000..3cb1a8bfe3f
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/Persistence/NoopPersistence.cs
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Int256;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat.Persistence;
+
+public class NoopPersistenceReader: IPersistence.IPersistenceReader
+{
+ public void Dispose()
+ {
+ }
+
+ public bool TryGetAccount(Address address, out Account? acc)
+ {
+ acc = null;
+ return false;
+ }
+
+ public bool TryGetSlot(Address address, in UInt256 index, out byte[] value)
+ {
+ value = null;
+ return false;
+ }
+
+ public StateId CurrentState => new StateId(0, Keccak.EmptyTreeHash);
+ public byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags)
+ {
+ return null;
+ }
+
+ public byte[]? GetAccountRaw(Hash256? addrHash)
+ {
+ return null;
+ }
+
+ public byte[]? GetStorageRaw(Hash256? addrHash, Hash256 slotHash)
+ {
+ return null;
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Persistence/RefCountingPersistenceReader.cs b/src/Nethermind/Nethermind.State/Flat/Persistence/RefCountingPersistenceReader.cs
new file mode 100644
index 00000000000..abaad7304ea
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/Persistence/RefCountingPersistenceReader.cs
@@ -0,0 +1,70 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Threading.Tasks;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Utils;
+using Nethermind.Int256;
+using Nethermind.Logging;
+using Nethermind.Trie;
+using Prometheus;
+
+namespace Nethermind.State.Flat.Persistence;
+
+public class RefCountingPersistenceReader : RefCountingDisposable, IPersistence.IPersistenceReader
+{
+ private readonly IPersistence.IPersistenceReader _innerReader;
+ private bool _isDisposed = false;
+
+ public RefCountingPersistenceReader(IPersistence.IPersistenceReader innerReader, ILogger logger)
+ {
+ _innerReader = innerReader;
+
+ string sTrace = Environment.StackTrace;
+ _ = Task.Run(async () =>
+ {
+ // Reader should be re-created every block unless something holds it for very long.
+ // It prevent database compaction, so this need to be closed eventually.
+ await Task.Delay(60_000);
+ if (!_isDisposed)
+ {
+ if (logger.IsWarn) logger.Warn($"Unexpected old snapshot created. Lease count {_leases.Value} at {sTrace}");
+ }
+ });
+ }
+
+ public bool TryGetAccount(Address address, out Account? acc)
+ {
+ return _innerReader.TryGetAccount(address, out acc);
+ }
+
+ public bool TryGetSlot(Address address, in UInt256 index, out byte[] value)
+ {
+ return _innerReader.TryGetSlot(address, in index, out value);
+ }
+
+ public StateId CurrentState => _innerReader.CurrentState;
+
+ public byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags)
+ {
+ return _innerReader.TryLoadRlp(address, in path, hash, flags);
+ }
+
+ public byte[]? GetAccountRaw(Hash256? addrHash)
+ {
+ return _innerReader.GetAccountRaw(addrHash);
+ }
+
+ public byte[]? GetStorageRaw(Hash256? addrHash, Hash256 slotHash)
+ {
+ return _innerReader.GetStorageRaw(addrHash, slotHash);
+ }
+
+ protected override void CleanUp()
+ {
+ _isDisposed = true;
+ _innerReader.Dispose();
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Persistence/RocksdbPersistence.cs b/src/Nethermind/Nethermind.State/Flat/Persistence/RocksdbPersistence.cs
new file mode 100644
index 00000000000..dd5bc6c4b6d
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/Persistence/RocksdbPersistence.cs
@@ -0,0 +1,668 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Autofac.Features.AttributeFilters;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Db;
+using Nethermind.Int256;
+using Nethermind.Serialization.Rlp;
+using Nethermind.State.Flat.ScopeProvider;
+using Nethermind.Trie;
+using Prometheus;
+using ZstdSharp;
+
+namespace Nethermind.State.Flat.Persistence;
+
+public class RocksdbPersistence : IPersistence
+{
+ private readonly IColumnsDb _db;
+ private static byte[] CurrentStateKey = Keccak.Compute("CurrentState").BytesToArray();
+
+ private const int StateKeyPrefixLength = 20;
+
+ private const int StorageHashPrefixLength = 20; // Store prefix of the 32 byte of the storage. Reduces index size.
+ private const int StorageSlotKeySize = 32;
+ private const int StorageKeyLength = StorageHashPrefixLength + StorageSlotKeySize;
+ private const int FullPathLength = 32;
+ private const int PathLengthLength = 1;
+
+ private const int StateNodesKeyLength = FullPathLength + PathLengthLength;
+ private const int StateNodesTopThreshold = 5;
+ private const int StateNodesTopPathLength = 3;
+ private const int StateNodesTopKeyLength = StateNodesTopPathLength + PathLengthLength;
+
+ private const int StorageNodesKeyLength = StorageHashPrefixLength + FullPathLength + PathLengthLength;
+ private const int StorageNodesTopThreshold = 3;
+ private const int StorageNodesTopPathLength = 2;
+ private const int StorageNodesTopKeyLength = StorageHashPrefixLength + StorageNodesTopPathLength + PathLengthLength;
+
+ internal AccountDecoder _accountDecoder = AccountDecoder.Instance;
+ private readonly IKeyValueStoreWithBatching _preimageDb;
+
+ // Compress accounts here instead of in rocksdb, allowing disabling rocksdb's compression.
+ // Unfortunately, only works well with accounts due to many redundant hash.
+ // TODO: Does not help with latency, or anything. Overall use slightly more disk space. Maybe remove.
+ private byte[] _zstdDictionary;
+ private readonly Configuration _configuration;
+ private readonly Histogram.Child _rocksdBPersistenceTimesSlotHit;
+ private readonly Histogram.Child _rocksdBPersistenceTimesSlotMiss;
+ private readonly Histogram.Child _rocksdBPersistenceTimesSlotCompareTime;
+ private readonly Histogram.Child _rocksdBPersistenceTimesAddressHash;
+
+ public record Configuration(
+ bool UsePreimage = false,
+ bool FlatInTrie = false,
+ bool SeparateStorageTop = true
+ )
+ {
+ }
+
+ private static Histogram _rocksdBPersistenceTimes = DevMetric.Factory.CreateHistogram("rocksdb_persistence_times", "aha", new HistogramConfiguration()
+ {
+ LabelNames = new[] { "type" },
+ // Buckets = Histogram.PowersOfTenDividedBuckets(2, 12, 5)
+ Buckets = [1]
+ });
+
+ public RocksdbPersistence(
+ IColumnsDb db,
+ [KeyFilter(DbNames.Preimage)] IDb preimageDb,
+ Configuration configuration)
+ {
+ _configuration = configuration;
+ _db = db;
+ _preimageDb = preimageDb;
+
+ LoadZstdDictionary();
+
+ _rocksdBPersistenceTimesAddressHash = _rocksdBPersistenceTimes.WithLabels("address_hash");
+ _rocksdBPersistenceTimesSlotHit = _rocksdBPersistenceTimes.WithLabels("slot_hash_hit");
+ _rocksdBPersistenceTimesSlotMiss = _rocksdBPersistenceTimes.WithLabels("slot_hash_miss");
+ _rocksdBPersistenceTimesSlotCompareTime = _rocksdBPersistenceTimes.WithLabels("slot_hash_compare_time");
+ // TrainDictionary();
+ }
+
+ /*
+ private Decompressor CreateDecompressor()
+ {
+ Decompressor decomp = new Decompressor();
+ decomp.LoadDictionary(_zstdDictionary);
+ return decomp;
+ }
+ */
+
+ private void LoadZstdDictionary()
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+ const string resourceName = "Nethermind.State.Flat.Persistence.zstddictionary.bin";
+ using Stream? stream = assembly.GetManifestResourceStream(resourceName)
+ ?? throw new InvalidOperationException($"Resource '{resourceName}' not found.");
+
+ using var ms = new MemoryStream();
+ stream.CopyTo(ms);
+ _zstdDictionary = ms.ToArray();
+ Console.Error.WriteLine($"Dictionary size is {_zstdDictionary.Length}");
+ }
+
+ internal void TrainDictionary()
+ {
+ using var snapshot = _db.CreateSnapshot();
+
+ List data = new List();
+
+ FlatDbColumns[] columnsToTest =
+ [
+ FlatDbColumns.State,
+ // FlatDbColumns.Storage,
+ // FlatDbColumns.StateTopNodes,
+ // FlatDbColumns.StateNodes,
+ // FlatDbColumns.StorageTopNodes,
+ // FlatDbColumns.StorageNodes,
+ ];
+
+ Random rand = new Random(0);
+
+ byte[] key = new byte[32];
+ byte[] maxKey = new byte[32];
+ Keccak.MaxValue.Bytes.CopyTo(maxKey);
+
+ int totalSize = 0;
+
+ foreach (FlatDbColumns column in columnsToTest)
+ {
+ ISortedKeyValueStore col = snapshot.GetColumn(column) as ISortedKeyValueStore;
+ for (int i = 0; i < 10000; i++)
+ {
+ rand.NextBytes(key);
+
+ using ISortedView view = col.GetViewBetween(key, maxKey);
+
+ if (view.MoveNext())
+ {
+ data.Add(view.CurrentValue.ToArray());
+ totalSize += view.CurrentValue.Length;
+ }
+ }
+ }
+
+ Console.Error.WriteLine($"Training dictionary");
+ byte[] dictionary = DictBuilder.TrainFromBuffer(data, 1024 * 2);
+ Console.Error.WriteLine($"Trained a dictionary of size {dictionary.Length} from {data.Count} samples of total size {totalSize}");
+
+ File.WriteAllBytes(Path.Combine(Directory.GetCurrentDirectory(), "flatdictionary.bin"), dictionary);
+
+ using Compressor compressor = new Compressor();
+ compressor.LoadDictionary(dictionary);
+
+ foreach (FlatDbColumns column in columnsToTest)
+ {
+ int compressed = 0;
+ int uncompressed = 0;
+
+ ISortedKeyValueStore col = snapshot.GetColumn(column) as ISortedKeyValueStore;
+ for (int i = 0; i < 10000; i++)
+ {
+ rand.NextBytes(key);
+
+ using ISortedView view = col.GetViewBetween(key, maxKey);
+
+ if (view.MoveNext())
+ {
+ data.Add(view.CurrentValue.ToArray());
+ totalSize += view.CurrentValue.Length;
+ }
+ }
+ for (int i = 0; i < 10000; i++)
+ {
+ rand.NextBytes(key);
+
+ using ISortedView view = col.GetViewBetween(key, maxKey);
+
+ if (view.MoveNext())
+ {
+ uncompressed += view.CurrentValue.Length;
+ compressed += compressor.Wrap(view.CurrentValue).Length;
+ }
+ }
+
+ Console.Error.WriteLine($"Expected ratio for {column} {(double)compressed / uncompressed}. Comppressed {compressed:N}, Uncompressed {uncompressed:N}");
+ }
+ }
+
+ internal static StateId ReadCurrentState(IReadOnlyKeyValueStore kv)
+ {
+ byte[] bytes = kv.Get(CurrentStateKey);
+ if (bytes is null || bytes.Length == 0)
+ {
+ return new StateId(-1, Keccak.EmptyTreeHash);
+ }
+
+ long blockNumber = BinaryPrimitives.ReadInt64BigEndian(bytes);
+ Hash256 stateHash = new Hash256(bytes[8..]);
+ return new StateId(blockNumber, stateHash);
+ }
+
+ internal static void SetCurrentState(IWriteOnlyKeyValueStore kv, StateId stateId)
+ {
+ Span bytes = stackalloc byte[8 + 32];
+ BinaryPrimitives.WriteInt64BigEndian(bytes[..8], stateId.blockNumber);
+ stateId.stateRoot.BytesAsSpan.CopyTo(bytes[8..]);
+
+ kv.PutSpan(CurrentStateKey, bytes);
+ }
+
+ private ReadOnlySpan EncodeAccountKey(Span buffer, in Address addr)
+ {
+ if (_configuration.UsePreimage)
+ {
+ addr.Bytes.CopyTo(buffer);
+ return buffer[..StateKeyPrefixLength];
+ }
+ else
+ {
+ ValueHash256 hashBuffer = ValueKeccak.Zero;
+ hashBuffer = addr.ToAccountPath;
+ hashBuffer.Bytes[..StorageHashPrefixLength].CopyTo(buffer);
+ return buffer[..StateKeyPrefixLength];
+ }
+ }
+
+ internal ReadOnlySpan EncodeStorageKey(Span buffer, in Address addr, in UInt256 slot)
+ {
+ if (_configuration.UsePreimage)
+ {
+ addr.Bytes.CopyTo(buffer);
+ slot.ToBigEndian(buffer[StorageHashPrefixLength..]);
+ return buffer[..StorageKeyLength];
+ }
+ else
+ {
+ ValueHash256 hashBuffer = ValueKeccak.Zero;
+ hashBuffer = addr.ToAccountPath; // 75ns on average
+ hashBuffer.Bytes[..StorageHashPrefixLength].CopyTo(buffer);
+
+ // around 300ns on average. 30% keccak cache hit rate.
+ StorageTree.ComputeKeyWithLookup(slot, buffer[StorageHashPrefixLength..(StorageHashPrefixLength + StorageSlotKeySize)]);
+
+ return buffer[..StorageKeyLength];
+ }
+ }
+
+ internal ReadOnlySpan EncodeStorageKeyHashed(Span buffer, in ValueHash256 addrHash, in ValueHash256 slotHash)
+ {
+ addrHash.Bytes[..StorageHashPrefixLength].CopyTo(buffer);
+ slotHash.Bytes.CopyTo(buffer[StorageHashPrefixLength..(StorageHashPrefixLength + StorageSlotKeySize)]);
+ return buffer[..StorageKeyLength];
+ }
+
+ internal static ReadOnlySpan EncodeStateNodeKey(Span buffer, in TreePath path)
+ {
+ path.Path.Bytes.CopyTo(buffer);
+ buffer[FullPathLength] = (byte)path.Length;
+ return buffer[..StateNodesKeyLength];
+ }
+
+ internal static ReadOnlySpan EncodeStateTopNodeKey(Span buffer, in TreePath path)
+ {
+ path.Path.Bytes[0..StateNodesTopPathLength].CopyTo(buffer);
+ buffer[StateNodesTopPathLength] = (byte)path.Length;
+ return buffer[..StateNodesTopKeyLength];
+ }
+
+ internal static ReadOnlySpan EncodeStorageNodeKey(Span buffer, Hash256 addr, in TreePath path)
+ {
+ addr.Bytes[..StorageHashPrefixLength].CopyTo(buffer);
+ path.Path.Bytes.CopyTo(buffer[StorageHashPrefixLength..]);
+ buffer[StorageHashPrefixLength + FullPathLength] = (byte)path.Length;
+ return buffer[..StorageNodesKeyLength];
+ }
+
+ internal static ReadOnlySpan EncodeStorageNodeTopKey(Span buffer, Hash256 addr, in TreePath path)
+ {
+ addr.Bytes[..StorageHashPrefixLength].CopyTo(buffer);
+ path.Path.Bytes[..StorageNodesTopPathLength].CopyTo(buffer[StorageHashPrefixLength..]);
+ buffer[StorageHashPrefixLength + StorageNodesTopPathLength] = (byte)path.Length;
+ return buffer[..StorageNodesTopKeyLength];
+ }
+
+ public IPersistence.IPersistenceReader CreateReader()
+ {
+ return new PersistenceReader(_db.CreateSnapshot(), this);
+ }
+
+ public IPersistence.IWriteBatch CreateWriteBatch(StateId from, StateId to)
+ {
+ var dbSnap = _db.CreateSnapshot();
+ var currentState = ReadCurrentState(dbSnap.GetColumn(FlatDbColumns.Metadata));
+ if (currentState != from)
+ {
+ dbSnap.Dispose();
+ throw new InvalidOperationException(
+ $"Attempted to apply snapshot on top of wrong state. Snapshot from: {from}, Db state: {currentState}");
+ }
+
+ Compressor compressor = new Compressor();
+ compressor.LoadDictionary(_zstdDictionary);
+
+ return new WriteBatch(this, _preimageDb.StartWriteBatch(), _db.StartWriteBatch(), dbSnap, compressor, to);
+ }
+
+ private class WriteBatch : IPersistence.IWriteBatch
+ {
+ private IWriteOnlyKeyValueStore state;
+ private IWriteOnlyKeyValueStore storage;
+ private IWriteOnlyKeyValueStore stateNodes;
+ private IWriteOnlyKeyValueStore stateTopNodes;
+ private IWriteOnlyKeyValueStore storageNodes;
+ private IWriteOnlyKeyValueStore storageTopNodes;
+
+ private ISortedKeyValueStore storageSnap;
+ private ISortedKeyValueStore storageNodesSnap;
+ private ISortedKeyValueStore storageTopNodesSnap;
+
+ private AccountDecoder _accountDecoder = AccountDecoder.Instance;
+
+ WriteFlags _flags = WriteFlags.None;
+ private readonly RocksdbPersistence _mainDb;
+ private readonly IWriteBatch _preimageWriteBatch;
+ private readonly IColumnsWriteBatch _batch;
+ private readonly IColumnDbSnapshot _dbSnap;
+ private readonly Compressor _compressor;
+ private readonly StateId _to;
+ private readonly bool _flatInTrie;
+ private readonly bool _separateStorageTop;
+
+ public WriteBatch(RocksdbPersistence mainDb,
+ IWriteBatch preimageWriteBatch,
+ IColumnsWriteBatch batch,
+ IColumnDbSnapshot dbSnap,
+ Compressor compressor,
+ StateId to)
+ {
+ _mainDb = mainDb;
+ _preimageWriteBatch = preimageWriteBatch;
+ _batch = batch;
+ _dbSnap = dbSnap;
+ _compressor = compressor;
+ _to = to;
+
+ _flatInTrie = mainDb._configuration.FlatInTrie;
+ _separateStorageTop = mainDb._configuration.SeparateStorageTop;
+ if (mainDb._configuration.FlatInTrie)
+ {
+ state = batch.GetColumnBatch(FlatDbColumns.StateNodes);
+ storage = batch.GetColumnBatch(FlatDbColumns.StorageNodes);
+ }
+ else
+ {
+ state = batch.GetColumnBatch(FlatDbColumns.State);
+ storage = batch.GetColumnBatch(FlatDbColumns.Storage);
+ }
+
+ stateNodes = batch.GetColumnBatch(FlatDbColumns.StateNodes);
+ stateTopNodes = batch.GetColumnBatch(FlatDbColumns.StateTopNodes);
+ storageNodes = batch.GetColumnBatch(FlatDbColumns.StorageNodes);
+ storageTopNodes = batch.GetColumnBatch(FlatDbColumns.StorageTopNodes);
+
+ storageSnap = ((ISortedKeyValueStore) dbSnap.GetColumn(FlatDbColumns.Storage));
+ storageNodesSnap = ((ISortedKeyValueStore) dbSnap.GetColumn(FlatDbColumns.StorageNodes));
+ storageTopNodesSnap = ((ISortedKeyValueStore)dbSnap.GetColumn(FlatDbColumns.StorageTopNodes));
+ }
+
+ public void Dispose()
+ {
+ SetCurrentState(_batch.GetColumnBatch(FlatDbColumns.Metadata), _to);
+ _batch.Dispose();
+ _dbSnap.Dispose();
+ _preimageWriteBatch.Dispose();
+ _compressor.Dispose();
+ }
+
+ public int SelfDestruct(Address addr)
+ {
+ ValueHash256 accountPath = addr.ToAccountPath;
+ Span firstKey = stackalloc byte[StorageHashPrefixLength]; // Because slot 0 is a thing, its just the address prefix.
+ Span lastKey = stackalloc byte[StorageNodesKeyLength];
+ firstKey.Fill(0x00);
+ lastKey.Fill(0xff);
+ accountPath.Bytes[..StorageHashPrefixLength].CopyTo(firstKey);
+ accountPath.Bytes[..StorageHashPrefixLength].CopyTo(lastKey);
+
+ int removedEntry = 0;
+ using (ISortedView storageNodeReader = storageNodesSnap.GetViewBetween(firstKey, lastKey))
+ {
+ var storageNodeWriter = storageNodes;
+ while (storageNodeReader.MoveNext())
+ {
+ storageNodeWriter.Remove(storageNodeReader.CurrentKey);
+ removedEntry++;
+ }
+ }
+
+ if (_separateStorageTop)
+ {
+ using (ISortedView storageNodeReader = storageTopNodesSnap.GetViewBetween(firstKey, lastKey))
+ {
+ var storageNodeWriter = storageNodes;
+ while (storageNodeReader.MoveNext())
+ {
+ storageNodeWriter.Remove(storageNodeReader.CurrentKey);
+ removedEntry++;
+ }
+ }
+ }
+
+ if (!_flatInTrie)
+ {
+ removedEntry = 0; // Debug
+ // for storage the prefix might change depending on the encoding
+ firstKey.Fill(0x00);
+ lastKey.Fill(0xff);
+ _mainDb.EncodeAccountKey(firstKey, addr);
+ _mainDb.EncodeAccountKey(lastKey, addr);
+ using (ISortedView storageReader = storageSnap.GetViewBetween(firstKey, lastKey))
+ {
+ IWriteOnlyKeyValueStore? storageWriter = storage;
+ while (storageReader.MoveNext())
+ {
+ storageWriter.Remove(storageReader.CurrentKey);
+ removedEntry++;
+ }
+ }
+ }
+
+ return removedEntry;
+ }
+
+ public void RemoveAccount(Address addr)
+ {
+ state.Remove(_mainDb.EncodeAccountKey(stackalloc byte[StateKeyPrefixLength], addr));
+ }
+
+ public void SetAccount(Address addr, Account account)
+ {
+ using var stream = _accountDecoder.EncodeToNewNettyStream(account);
+ state.PutSpan(_mainDb.EncodeAccountKey(stackalloc byte[StateKeyPrefixLength], addr), stream.AsSpan());
+ }
+
+ public void SetStorage(Address addr, UInt256 slot, ReadOnlySpan value)
+ {
+ ValueHash256 hash256 = ValueKeccak.Zero;
+ StorageTree.ComputeKeyWithLookup(slot, hash256.BytesAsSpan);
+ _preimageWriteBatch.PutSpan(hash256.Bytes, slot.ToBigEndian());
+
+ ReadOnlySpan theKey = _mainDb.EncodeStorageKey(stackalloc byte[StorageKeyLength], addr, slot);
+ storage.PutSpan(theKey, value, _flags);
+ }
+
+ public void RemoveStorage(Address addr, UInt256 slot)
+ {
+ ReadOnlySpan theKey = _mainDb.EncodeStorageKey(stackalloc byte[StorageKeyLength], addr, slot);
+ storage.Remove(theKey);
+ }
+
+ public void SetStorageRaw(Hash256 addrHash, Hash256 slotHash, ReadOnlySpan value)
+ {
+ if (_mainDb._configuration.UsePreimage) throw new InvalidOperationException("Cannot set raw when using preimage");
+
+ storage.PutSpan(_mainDb.EncodeStorageKeyHashed(stackalloc byte[StorageKeyLength], addrHash.ValueHash256, slotHash.ValueHash256), value, _flags);
+ }
+
+ public void SetAccountRaw(Hash256 addrHash, Account account)
+ {
+ if (_mainDb._configuration.UsePreimage) throw new InvalidOperationException("Cannot set raw when using preimage");
+ using var stream = _accountDecoder.EncodeToNewNettyStream(account);
+
+ state.PutSpan(addrHash.Bytes[..StateKeyPrefixLength], stream.AsSpan(), _flags);
+ }
+
+ public void SetTrieNodes(Hash256? address, TreePath path, TrieNode tn)
+ {
+ if (address is null)
+ {
+ if (path.Length <= StateNodesTopThreshold)
+ {
+ stateTopNodes.PutSpan(EncodeStateTopNodeKey(stackalloc byte[StateNodesTopKeyLength], path), tn.FullRlp.Span, _flags);
+ }
+ else
+ {
+ stateNodes.PutSpan(EncodeStateNodeKey(stackalloc byte[StateNodesKeyLength], path), tn.FullRlp.Span, _flags);
+ }
+ }
+ else
+ {
+ if (_separateStorageTop && path.Length <= StorageNodesTopThreshold)
+ {
+ storageTopNodes.PutSpan(EncodeStorageNodeTopKey(stackalloc byte[StorageNodesTopKeyLength], address, path), tn.FullRlp.Span, _flags);
+ }
+ else
+ {
+ storageNodes.PutSpan(EncodeStorageNodeKey(stackalloc byte[StorageNodesKeyLength], address, path), tn.FullRlp.Span, _flags);
+ }
+ }
+ }
+ }
+
+ private class PersistenceReader : IPersistence.IPersistenceReader
+ {
+ private readonly IColumnDbSnapshot _db;
+ private readonly IReadOnlyKeyValueStore _state;
+ private readonly IReadOnlyKeyValueStore _storage;
+ private readonly IReadOnlyKeyValueStore _stateNodes;
+ private readonly IReadOnlyKeyValueStore _stateTopNodes;
+ private readonly IReadOnlyKeyValueStore _storageNodes;
+ private readonly IReadOnlyKeyValueStore _storageTopNodes;
+ private readonly RocksdbPersistence _mainDb;
+ private readonly bool _usePreimage;
+ private readonly bool _flatInTrie;
+ private readonly bool _separateStorageTop;
+
+ public PersistenceReader(IColumnDbSnapshot db, RocksdbPersistence mainDb)
+ {
+ _usePreimage = mainDb._configuration.UsePreimage;
+ _flatInTrie = mainDb._configuration.FlatInTrie;
+ _separateStorageTop = mainDb._configuration.SeparateStorageTop;
+ _db = db;
+ _mainDb = mainDb;
+ CurrentState = ReadCurrentState(db.GetColumn(FlatDbColumns.Metadata));
+ if (_flatInTrie)
+ {
+ _state = _db.GetColumn(FlatDbColumns.StateNodes);
+ _storage = _db.GetColumn(FlatDbColumns.StorageNodes);
+ }
+ else
+ {
+ _state = _db.GetColumn(FlatDbColumns.State);
+ _storage = _db.GetColumn(FlatDbColumns.Storage);
+ }
+ _stateNodes = _db.GetColumn(FlatDbColumns.StateNodes);
+ _stateTopNodes = _db.GetColumn(FlatDbColumns.StateTopNodes);
+ _storageNodes = _db.GetColumn(FlatDbColumns.StorageNodes);
+ _storageTopNodes = _db.GetColumn(FlatDbColumns.StorageTopNodes);
+ }
+
+ public StateId CurrentState { get; }
+
+ public void Dispose()
+ {
+ _db.Dispose();
+ }
+
+ /*
+ private Decompressor RentDecompressor()
+ {
+ Decompressor? decompressor = _decompressor;
+ if (decompressor is null) return _mainDb.CreateDecompressor();
+ if (Interlocked.CompareExchange(ref _decompressor, null, decompressor) == decompressor) return decompressor;
+ return _mainDb.CreateDecompressor();
+ }
+
+ private void ReturnDecompressor(Decompressor decompressor)
+ {
+ if (Interlocked.CompareExchange(ref _decompressor, decompressor, null) == null)
+ {
+ return;
+ }
+ decompressor.Dispose();
+ }
+ */
+
+ public bool TryGetAccount(Address address, out Account? acc)
+ {
+ Span value = _state.GetSpan(_mainDb.EncodeAccountKey(stackalloc byte[StateKeyPrefixLength], address));
+ try
+ {
+ if (address == FlatWorldStateScope.DebugAddress)
+ {
+ Console.Error.WriteLine($"Get {address}, got {value.ToHexString()}");
+ }
+ if (value.IsNullOrEmpty())
+ {
+ acc = null;
+ return true;
+ }
+
+ var ctx = new Rlp.ValueDecoderContext(value);
+ acc = _mainDb._accountDecoder.Decode(ref ctx);
+ return true;
+ }
+ finally
+ {
+ _state.DangerousReleaseMemory(value);
+ }
+ }
+
+ public bool TryGetSlot(Address address, in UInt256 index, out byte[] valueBytes)
+ {
+ ReadOnlySpan theKey = _mainDb.EncodeStorageKey(stackalloc byte[StorageKeyLength], address, index);
+ Span value = _storage.GetSpan(theKey);
+ try
+ {
+ if (value.IsNullOrEmpty())
+ {
+ valueBytes = null;
+ return true;
+ }
+
+ valueBytes = value.ToArray();
+ return true;
+ }
+ finally
+ {
+ _storage.DangerousReleaseMemory(value);
+ }
+ }
+
+ public byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags)
+ {
+ if (address is null)
+ {
+ if (path.Length <= StateNodesTopThreshold)
+ {
+ return _stateTopNodes.Get(EncodeStateTopNodeKey(stackalloc byte[StateNodesTopKeyLength], in path));
+ }
+ else
+ {
+ return _stateNodes.Get(EncodeStateNodeKey(stackalloc byte[StateNodesKeyLength], in path));
+ }
+ }
+ else
+ {
+ if (_separateStorageTop && path.Length <= StorageNodesTopThreshold)
+ {
+ return _storageTopNodes.Get(EncodeStorageNodeTopKey(stackalloc byte[StorageNodesTopKeyLength], address, in path));
+ }
+ else
+ {
+ return _storageNodes.Get(EncodeStorageNodeKey(stackalloc byte[StorageNodesKeyLength], address, in path));
+ }
+ }
+ }
+
+ public byte[]? GetAccountRaw(Hash256 addrHash)
+ {
+ return GetAccountRaw(addrHash.ValueHash256);
+ }
+
+ private byte[]? GetAccountRaw(in ValueHash256 accountHash)
+ {
+ if (_usePreimage) throw new InvalidOperationException("Raw operation not available in preimage mode");
+ return _state.GetSpan(accountHash.Bytes[..StateKeyPrefixLength]).ToArray();
+ }
+
+ public byte[]? GetStorageRaw(Hash256? addrHash, Hash256 slotHash)
+ {
+ if (_usePreimage) throw new InvalidOperationException("Raw operation not available in preimage mode");
+ Span keySpan = stackalloc byte[StorageKeyLength];
+ ReadOnlySpan storageKey = _mainDb.EncodeStorageKeyHashed(keySpan, addrHash.ValueHash256, slotHash.ValueHash256);
+ return _storage.Get(storageKey);
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Persistence/zstddictionary.bin b/src/Nethermind/Nethermind.State/Flat/Persistence/zstddictionary.bin
new file mode 100644
index 00000000000..ddbdc07779a
Binary files /dev/null and b/src/Nethermind/Nethermind.State/Flat/Persistence/zstddictionary.bin differ
diff --git a/src/Nethermind/Nethermind.State/Flat/ReadonlyReaderRepository.cs b/src/Nethermind/Nethermind.State/Flat/ReadonlyReaderRepository.cs
new file mode 100644
index 00000000000..98866a22199
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ReadonlyReaderRepository.cs
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Concurrent;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Utils;
+
+namespace Nethermind.State.Flat;
+
+public class ReadonlyReaderRepository
+{
+ private ConcurrentDictionary> _sharedReader = new();
+ private readonly IFlatDiffRepository _flatDiffRepository;
+
+ public ReadonlyReaderRepository(IFlatDiffRepository flatDiffRepository)
+ {
+ flatDiffRepository.ReorgBoundaryReached += (sender, reached) => ClearAllReader();
+ _flatDiffRepository = flatDiffRepository;
+ }
+
+ private void ClearAllReader()
+ {
+ // Readers take up a persistence snapshot which which eventually slow down the db. So we need to clear them
+ // on persist, that way a new snapshot will be used later.
+ using ArrayPoolListRef toRemoves = new ArrayPoolListRef(_sharedReader.Count, _sharedReader.Keys);
+
+ foreach (var stateId in toRemoves)
+ {
+ if (_sharedReader.TryRemove(stateId, out RefCountingDisposableBox snapshotBundle))
+ {
+ snapshotBundle.Dispose();
+ }
+ }
+ }
+
+ public RefCountingDisposableBox? GatherReadOnlyReaderAtBaseBlock(StateId baseBlock)
+ {
+ if (_sharedReader.TryGetValue(baseBlock, out var snapshotBundle) && snapshotBundle.TryAcquire())
+ {
+ return snapshotBundle;
+ }
+
+ SnapshotBundle? bundle = _flatDiffRepository.GatherReaderAtBaseBlock(baseBlock, IFlatDiffRepository.SnapshotBundleUsage.StateReader);
+ if (bundle is null) return null;
+
+ RefCountingDisposableBox newReader = new RefCountingDisposableBox(bundle);
+ newReader.AcquireLease();
+ if (!_sharedReader.TryAdd(baseBlock, newReader))
+ {
+ newReader.Dispose();
+ }
+
+ return newReader;
+ }
+
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/AbstractMinimalTrieStore.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/AbstractMinimalTrieStore.cs
new file mode 100644
index 00000000000..f28a27448df
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/AbstractMinimalTrieStore.cs
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Trie;
+using Nethermind.Trie.Pruning;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public abstract class AbstractMinimalTrieStore: IScopedTrieStore
+{
+ public abstract TrieNode FindCachedOrUnknown(in TreePath path, Hash256 hash);
+
+ public abstract byte[]? TryLoadRlp(in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None);
+ public abstract ICommitter BeginCommit(TrieNode? root, WriteFlags writeFlags = WriteFlags.None);
+
+
+ public byte[]? LoadRlp(in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None)
+ {
+ byte[]? value = TryLoadRlp(path, hash, flags);
+ if (value is null)
+ {
+ throw new TrieNodeException($"Missing trie node. {path}:{hash}", path, hash);
+ }
+
+ return value;
+ }
+
+ public virtual ITrieNodeResolver GetStorageTrieNodeResolver(Hash256? address) => throw new UnsupportedOperationException("Get trie node resolver not supported");
+
+ public INodeStorage.KeyScheme Scheme => INodeStorage.KeyScheme.HalfPath;
+
+ public bool IsPersisted(in TreePath path, in ValueHash256 keccak) => throw new UnsupportedOperationException("Persisted check not supported");
+
+ public abstract class AbstractMinimalCommitter(ConcurrencyQuota quota) : ICommitter
+ {
+ public void Dispose()
+ {
+ }
+
+ public abstract TrieNode CommitNode(ref TreePath path, TrieNode node);
+
+ bool ICommitter.TryRequestConcurrentQuota() => quota.TryRequestConcurrencyQuota();
+ void ICommitter.ReturnConcurrencyQuota() => quota.ReturnConcurrencyQuota();
+ }
+
+ public class UnsupportedOperationException(string message) : Exception(message)
+ {
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/ConcurrencyQuota.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/ConcurrencyQuota.cs
new file mode 100644
index 00000000000..70c31a9c1b3
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/ConcurrencyQuota.cs
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Threading;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public class ConcurrencyQuota()
+{
+ private int _concurrency = Environment.ProcessorCount;
+
+ public bool TryRequestConcurrencyQuota()
+ {
+ if (Interlocked.Decrement(ref _concurrency) >= 0)
+ {
+ return true;
+ }
+
+ ReturnConcurrencyQuota();
+ return false;
+ }
+
+ public void ReturnConcurrencyQuota() => Interlocked.Increment(ref _concurrency);
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatScopeProvider.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatScopeProvider.cs
new file mode 100644
index 00000000000..6b5e43ffc18
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatScopeProvider.cs
@@ -0,0 +1,73 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Autofac.Features.AttributeFilters;
+using Nethermind.Core;
+using Nethermind.Db;
+using Nethermind.Evm.State;
+using Nethermind.Logging;
+using Org.BouncyCastle.Bcpg;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public class FlatScopeProvider : IWorldStateScopeProvider
+{
+ private readonly IFlatDiffRepository _flatDiffRepository;
+ private readonly ILogManager _logManager;
+ private readonly TrieStoreScopeProvider.KeyValueWithBatchingBackedCodeDb _codeDb;
+ private readonly bool _isReadOnly;
+ private readonly FlatDiffRepository.Configuration _configuration;
+ private readonly ITrieWarmer _trieWarmer;
+ private readonly ResourcePool _resourcePool;
+ private readonly IFlatDiffRepository.SnapshotBundleUsage _usage;
+
+ public FlatScopeProvider(
+ [KeyFilter(DbNames.Code)] IDb codeDb,
+ IFlatDiffRepository flatDiffRepository,
+ FlatDiffRepository.Configuration configuration,
+ ITrieWarmer trieWarmer,
+ ResourcePool resourcePool,
+ IFlatDiffRepository.SnapshotBundleUsage usage,
+ ILogManager logManager,
+ bool isReadOnly = false)
+ {
+ _flatDiffRepository = flatDiffRepository;
+ _configuration = configuration;
+ _trieWarmer = trieWarmer;
+ _resourcePool = resourcePool;
+ _usage = usage;
+ _logManager = logManager;
+ _codeDb = new TrieStoreScopeProvider.KeyValueWithBatchingBackedCodeDb(codeDb);
+ _isReadOnly = isReadOnly;
+ }
+
+ public bool HasRoot(BlockHeader? baseBlock)
+ {
+ return _flatDiffRepository.HasStateForBlock(new StateId(baseBlock));
+ }
+
+ public IWorldStateScopeProvider.IScope BeginScope(BlockHeader? baseBlock)
+ {
+ StateId currentState = new StateId(baseBlock);
+ SnapshotBundle snapshotBundle = _flatDiffRepository.GatherReaderAtBaseBlock(currentState, usage: _usage);
+ if (_trieWarmer is NoopTrieWarmer) snapshotBundle.SetPrewarmer();
+
+ ITrieWarmer warmer = _trieWarmer;
+ if (_configuration.DisableTrieWarmer)
+ {
+ warmer = new NoopTrieWarmer();
+ }
+
+ return new FlatWorldStateScope(
+ currentState,
+ snapshotBundle,
+ _codeDb,
+ _flatDiffRepository,
+ _configuration,
+ warmer,
+ _resourcePool,
+ _logManager,
+ _isReadOnly
+ );
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatStorageTree.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatStorageTree.cs
new file mode 100644
index 00000000000..505607d6493
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatStorageTree.cs
@@ -0,0 +1,202 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Evm.State;
+using Nethermind.Int256;
+using Nethermind.Logging;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public class FlatStorageTree : IWorldStateScopeProvider.IStorageTree
+{
+ private readonly StorageTree _tree;
+ private readonly StorageTree _warmupStorageTree;
+ private readonly Address _address;
+ private readonly FlatDiffRepository.Configuration _config;
+ private readonly ITrieWarmer _trieCacheWarmer;
+ private readonly FlatWorldStateScope _scope;
+ private readonly SnapshotBundle _bundle;
+ private readonly Hash256 _addressHash;
+ private readonly StorageTrieStoreAdapter _storageTrieAdapter;
+ private readonly StorageTrieStoreAdapter _warmerStorageTrieAdapter;
+
+ // This number is the idx of the snapshot in the SnapshotBundle where a clear for this account was found.
+ // This is passed to TryGetSlot which prevent it from reading before self destruct.
+ private int _selfDestructKnownStateIdx;
+
+ public FlatStorageTree(
+ FlatWorldStateScope scope,
+ ITrieWarmer trieCacheWarmer,
+ SnapshotBundle bundle,
+ FlatDiffRepository.Configuration config,
+ ConcurrencyQuota concurrencyQuota,
+ Hash256 storageRoot,
+ Address address,
+ ILogManager logManager)
+ {
+ _scope = scope;
+ _trieCacheWarmer = trieCacheWarmer;
+ _bundle = bundle;
+ _address = address;
+ _addressHash = address.ToAccountPath.ToHash256();
+ _selfDestructKnownStateIdx = bundle.DetermineSelfDestructSnapshotIdx(address);
+
+ _storageTrieAdapter = new StorageTrieStoreAdapter(bundle, concurrencyQuota, _addressHash, _selfDestructKnownStateIdx,
+ isTrieWarmer: false);
+ _warmerStorageTrieAdapter = new StorageTrieStoreAdapter(bundle, concurrencyQuota, _addressHash, _selfDestructKnownStateIdx,
+ isTrieWarmer: true);
+
+ _tree = new StorageTree(_storageTrieAdapter, storageRoot, logManager);
+ _tree.RootHash = storageRoot;
+
+ _warmupStorageTree = new StorageTree(_warmerStorageTrieAdapter, logManager);
+ _warmupStorageTree.RootHash = storageRoot;
+
+ _config = config;
+
+ // In case its all write.
+ // TODO: Check hint set is working or not.
+ _trieCacheWarmer.PushJob(_scope, null, this, 0, _scope.HintSequenceId);
+ }
+
+ public Hash256 RootHash => _tree.RootHash;
+ public byte[] Get(in UInt256 index)
+ {
+ if (!_config.ReadWithTrie && TryGet(index, out var value))
+ {
+ if (value == null) value = State.StorageTree.ZeroBytes;
+
+ if (_config.VerifyWithTrie)
+ {
+ var treeValue = _tree.Get(index);
+ if (!Bytes.AreEqual(treeValue, value))
+ {
+ throw new Exception($"Get slot got wrong value. Address {_address}, {_tree.RootHash}, {index}. Tree: {treeValue?.ToHexString()} vs Flat: {value?.ToHexString()}. Self destruct it {_selfDestructKnownStateIdx}");
+ }
+ }
+
+ HintGet(index, value);
+ return value;
+ }
+ else
+ {
+ value = _tree.Get(index);
+ HintGet(index, value);
+ return value;
+ }
+ }
+
+ public void HintGet(in UInt256 index, byte[]? value)
+ {
+ // Note: VERY hot code.
+ // 90% of the read goes through prewarmer, not actually go through this class, meaning this method is called
+ // a lot. Unlike with account, setting the setted slot have a measurable net negative impact on performance.
+ // Trying to set this value async through trie warmer proved to be hard to pull of and result in random invalid
+ // block.
+ WarmUpSlot(index);
+ }
+
+ public void HintSet(in UInt256 index)
+ {
+ WarmUpSlot(index);
+ }
+
+ private void WarmUpSlot(UInt256 index)
+ {
+ _trieCacheWarmer.PushJob(_scope, null, this, index, _scope.HintSequenceId);
+ }
+
+ // Called by trie warmer.
+ public bool WarUpStorageTrie(UInt256 index, int sequenceId)
+ {
+ if (_scope.HintSequenceId != sequenceId) return false;
+
+ if (_bundle.ShouldPrewarm(_address, index))
+ {
+ // Note: storage tree root not changed after write batch. Also not cleared. So the result is not correct.
+ // this is just to warm up the nodes.
+ ValueHash256 key = ValueKeccak.Zero;
+ StorageTree.ComputeKeyWithLookup(index, key.BytesAsSpan);
+ _ = _warmupStorageTree.Get(key.BytesAsSpan, keepChildRef: true);
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool TryGet(in UInt256 index, out byte[]? value)
+ {
+ return _bundle.TryGetSlot(_address, index, _selfDestructKnownStateIdx, out value);
+ }
+
+ public byte[] Get(in ValueHash256 hash)
+ {
+ throw new Exception("Not supported");
+ }
+
+ private void Set(UInt256 slot, byte[] value)
+ {
+ _bundle.SetChangedSlot(_address, slot, value);
+ }
+
+ public void SelfDestruct()
+ {
+ _bundle.Clear(_address, _addressHash);
+ _selfDestructKnownStateIdx = _bundle.DetermineSelfDestructSnapshotIdx(_address);
+
+ // Technically, they wont actually matter as the trie will traverse the existing path anyway and on self destruct
+ // it will just get blocked on root, so this is more of an optimization.
+ _storageTrieAdapter.SelfDestructKnownStateIdx = _selfDestructKnownStateIdx;
+ _warmerStorageTrieAdapter.SelfDestructKnownStateIdx = _selfDestructKnownStateIdx;
+ }
+
+ public void CommitTree()
+ {
+ _tree.Commit();
+ }
+
+ public IWorldStateScopeProvider.IStorageWriteBatch CreateWriteBatch(int estimatedEntries, Action onRootUpdated)
+ {
+ TrieStoreScopeProvider.StorageTreeBulkWriteBatch storageTreeBulkWriteBatch =
+ new TrieStoreScopeProvider.StorageTreeBulkWriteBatch(
+ estimatedEntries,
+ _tree,
+ onRootUpdated,
+ _address,
+ commit: true);
+
+ return new StorageTreeBulkWriteBatch(
+ storageTreeBulkWriteBatch,
+ this
+ );
+ }
+
+ private class StorageTreeBulkWriteBatch(
+ TrieStoreScopeProvider.StorageTreeBulkWriteBatch storageTreeBulkWriteBatch,
+ FlatStorageTree storageTree) : IWorldStateScopeProvider.IStorageWriteBatch
+ {
+ public void Set(in UInt256 index, byte[] value)
+ {
+ storageTreeBulkWriteBatch.Set(in index, value);
+ storageTree.Set(index, value);
+ }
+
+ public void Clear()
+ {
+ storageTreeBulkWriteBatch.Clear();
+ storageTree.SelfDestruct();
+ }
+
+ public void Dispose()
+ {
+ storageTreeBulkWriteBatch.Dispose();
+ }
+ }
+}
+
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatWorldStateManager.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatWorldStateManager.cs
new file mode 100644
index 00000000000..5b8cb6123e4
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatWorldStateManager.cs
@@ -0,0 +1,129 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Threading;
+using Autofac.Features.AttributeFilters;
+using Nethermind.Config;
+using Nethermind.Core;
+using Nethermind.Db;
+using Nethermind.Evm.State;
+using Nethermind.Logging;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.State.SnapServer;
+using Nethermind.Trie;
+using Nethermind.Trie.Pruning;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public class FlatWorldStateManager : IWorldStateManager
+{
+ private readonly IFlatDiffRepository _flatDiffRepository;
+ private readonly FlatStateReader _flatStateReader;
+ private readonly IProcessExitSource _exitSource;
+ private readonly IDb _codeDb;
+ private readonly ILogManager _logManager;
+ private readonly FlatDiffRepository.Configuration _configuration;
+ private readonly FlatScopeProvider _mainWorldState;
+ private readonly ResourcePool _resourcePool;
+
+ public FlatWorldStateManager(
+ IFlatDiffRepository flatDiffRepository,
+ FlatDiffRepository.Configuration configuration,
+ FlatStateReader flatStateReader,
+ TrieWarmer trieWarmer,
+ IProcessExitSource exitSource,
+ [KeyFilter(DbNames.Code)] IDb codeDb,
+ ResourcePool resourcePool,
+ ILogManager logManager
+ )
+ {
+ _flatDiffRepository = flatDiffRepository;
+ _flatStateReader = flatStateReader;
+ _codeDb = codeDb;
+ _logManager = logManager;
+ _configuration = configuration;
+ _exitSource = exitSource;
+ _resourcePool = resourcePool;
+ _mainWorldState = new FlatScopeProvider(
+ codeDb,
+ flatDiffRepository,
+ configuration,
+ trieWarmer,
+ resourcePool,
+ IFlatDiffRepository.SnapshotBundleUsage.MainBlockProcessing,
+ logManager);
+ }
+
+ public IWorldStateScopeProvider GlobalWorldState => _mainWorldState;
+ public IStateReader GlobalStateReader => _flatStateReader;
+ public ISnapServer? SnapServer => null;
+ public IReadOnlyKeyValueStore? HashServer => null;
+ public IWorldStateScopeProvider CreateResettableWorldState()
+ {
+ return new FlatScopeProvider(
+ _codeDb,
+ _flatDiffRepository,
+ _configuration,
+ new NoopTrieWarmer(),
+ _resourcePool,
+ IFlatDiffRepository.SnapshotBundleUsage.ReadOnlyProcessingEnv,
+ _logManager,
+ isReadOnly: true);
+ }
+
+ event EventHandler? IWorldStateManager.ReorgBoundaryReached
+ {
+ add => _flatDiffRepository.ReorgBoundaryReached += value;
+ remove => _flatDiffRepository.ReorgBoundaryReached -= value;
+ }
+
+ public IOverridableWorldScope CreateOverridableWorldScope()
+ {
+ var scopeProvider = new FlatScopeProvider(
+ _codeDb,
+ _flatDiffRepository,
+ _configuration,
+ new NoopTrieWarmer(),
+ _resourcePool,
+ IFlatDiffRepository.SnapshotBundleUsage.ReadOnlyProcessingEnv,
+ _logManager,
+ isReadOnly: true);
+ return new FakeOverridableWorldScope(scopeProvider, _flatStateReader);
+ }
+
+ public bool VerifyTrie(BlockHeader stateAtBlock, CancellationToken cancellationToken)
+ {
+ using IPersistence.IPersistenceReader reader = _flatDiffRepository.LeaseReader();
+ FlatVerifyTrieVisitor trieVisitor = new FlatVerifyTrieVisitor(_codeDb, reader, _logManager, cancellationToken);
+
+ // Just a bit hacky due to mistmatch with best persisted state and actually persisted state.
+ StateId? stateId = _flatDiffRepository.FindLatestAvailableState();
+
+ // StateId? stateId = _flatDiffRepository.FindStateIdForStateRoot(stateAtBlock.StateRoot);
+ _flatStateReader.RunTreeVisitor(trieVisitor, stateId.Value.stateRoot.ToHash256(), new VisitingOptions()
+ {
+ });
+
+ if (trieVisitor.Stats.MismatchedAccount > 0 || trieVisitor.Stats.MismatchedSlot > 0)
+ {
+ _exitSource.Exit(10);
+ }
+
+ return true;
+ }
+
+ public void FlushCache(CancellationToken cancellationToken)
+ {
+ _flatDiffRepository.FlushCache(cancellationToken);
+ }
+
+ public class FakeOverridableWorldScope(IWorldStateScopeProvider worldState, IStateReader stateReader) : IOverridableWorldScope
+ {
+ public IWorldStateScopeProvider WorldState => worldState;
+ public IStateReader GlobalStateReader => stateReader;
+ public void ResetOverrides()
+ {
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatWorldStateScope.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatWorldStateScope.cs
new file mode 100644
index 00000000000..db9ad6651b1
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/FlatWorldStateScope.cs
@@ -0,0 +1,330 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Evm.State;
+using Nethermind.Int256;
+using Nethermind.Logging;
+using Nethermind.Trie;
+using Prometheus;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public class FlatWorldStateScope : IWorldStateScopeProvider.IScope
+{
+ // internal static Address DebugAddress = new Address("0x2c2b2df915e31d27e7a24c7c3cf9b114208a45e0");
+ internal static Address DebugAddress = new Address("0x6ffedc1562918c07ae49b0ba210e6d80c7d61eab");
+ internal static UInt256 DebugSlot = UInt256.Parse("0");
+
+ private static Histogram _snapshotBundleTimes = DevMetric.Factory.CreateHistogram("flat_write_batch", "aha", new HistogramConfiguration()
+ {
+ LabelNames = new[] { "type" },
+ // Buckets = Histogram.PowersOfTenDividedBuckets(2, 12, 5)
+ Buckets = [1]
+ });
+
+ private readonly SnapshotBundle _snapshotBundle;
+ private readonly IWorldStateScopeProvider.ICodeDb _codeDb;
+ private readonly IFlatDiffRepository _flatDiffRepository;
+ private readonly Dictionary _storages = new();
+ private readonly StateTree _stateTree;
+ private readonly PatriciaTree _warmupStateTree;
+ private readonly ILogManager _logManager;
+ private readonly bool _isReadOnly;
+ private readonly FlatDiffRepository.Configuration _configuration;
+ private readonly ConcurrencyQuota _concurrencyQuota;
+ private readonly ITrieWarmer _warmer;
+
+ // The sequence id is for stopping trie warmer for doing work while committing. Incrementing this value invalidates
+ // tasks within the trie warmers's ring buffer.
+ private int _hintSequenceId = 0;
+ private StateId _currentStateId;
+ private readonly ResourcePool _resourcePool;
+
+ public FlatWorldStateScope(
+ StateId currentStateId,
+ SnapshotBundle snapshotBundle,
+ IWorldStateScopeProvider.ICodeDb codeDb,
+ IFlatDiffRepository flatDiffRepository,
+ FlatDiffRepository.Configuration configuration,
+ ITrieWarmer trieCacheWarmer,
+ ResourcePool resourcePool,
+ ILogManager logManager,
+ bool isReadOnly = false)
+ {
+ _currentStateId = currentStateId;
+ _snapshotBundle = snapshotBundle;
+ _codeDb = codeDb;
+ _flatDiffRepository = flatDiffRepository;
+ _resourcePool = resourcePool;
+
+ _concurrencyQuota = new ConcurrencyQuota(); // Used during tree commit.
+ _stateTree = new StateTree(
+ new StateTrieStoreAdapter(snapshotBundle, _concurrencyQuota, isTrieWarmer: false),
+ logManager
+ );
+ _stateTree.RootHash = currentStateId.stateRoot.ToCommitment();
+ _warmupStateTree = new PatriciaTree(
+ new StateTrieStoreAdapter(snapshotBundle, _concurrencyQuota, isTrieWarmer: true),
+ logManager
+ );
+ _warmupStateTree.RootHash = currentStateId.stateRoot.ToCommitment();
+
+ _configuration = configuration;
+ _logManager = logManager;
+ _warmer = trieCacheWarmer;
+ _warmer.OnNewScope();
+ _isReadOnly = isReadOnly;
+ }
+
+ public void Dispose() => _snapshotBundle.Dispose();
+ public Hash256 RootHash => _stateTree.RootHash;
+ public void UpdateRootHash() => _stateTree.UpdateRootHash();
+
+ public Account? Get(Address address)
+ {
+ if (!_configuration.ReadWithTrie && _snapshotBundle.TryGetAccount(address, out Account account))
+ {
+ HintGet(address, account);
+
+ if (address == DebugAddress)
+ {
+ Account? accTrie = _stateTree.Get(address);
+ Console.Error.WriteLine($"Address Get {account}. Tree {accTrie}");
+ }
+
+ if (_configuration.VerifyWithTrie)
+ {
+ Account? accTrie = _stateTree.Get(address);
+ if (accTrie != account)
+ {
+ throw new Exception($"Incorrect account {address}, account hash {address.ToAccountPath}, trie: {accTrie} vs flat: {account}");
+ }
+ }
+
+ return account;
+ }
+ else
+ {
+ account = _stateTree.Get(address);
+ HintGet(address, account);
+ return account;
+ }
+ }
+
+ public void HintGet(Address address, Account? account)
+ {
+ _warmer.PushJob(this, address, null, null, _hintSequenceId);
+
+ // during storage root update, the account will get re-fetched then updated.
+ _snapshotBundle.SetAccount(address, account);
+ }
+
+ public void HintSet(Address address)
+ {
+ _warmer.PushJob(this, address, null, null, _hintSequenceId);
+ }
+
+ public IWorldStateScopeProvider.ICodeDb CodeDb => _codeDb;
+ public int HintSequenceId => _hintSequenceId; // Called by FlatStorageTree
+
+ public bool WarmUpStateTrie(Address address, int sequenceId)
+ {
+ if (_hintSequenceId != sequenceId) return false;
+
+ try
+ {
+ if (_snapshotBundle.ShouldPrewarm(address, null))
+ {
+ // Note: tree root not changed after write batch. Also not cleared. So the result is not correct.
+ // this is just for warming up
+ _ = _warmupStateTree.Get(address.ToAccountPath.Bytes, keepChildRef: true);
+ }
+ }
+ catch (AbstractMinimalTrieStore.UnsupportedOperationException)
+ {
+ // So there is this highly confusing case where patriciatree attempted to set storage nodes as persisted
+ // if its parent is persisted. No idea what is the case, but in this case, we really dont care.
+ }
+
+ return true;
+ }
+
+ public IWorldStateScopeProvider.IStorageTree CreateStorageTree(Address address) => CreateStorageTreeImpl(address);
+
+ private FlatStorageTree CreateStorageTreeImpl(Address address)
+ {
+ ref FlatStorageTree storage = ref CollectionsMarshal.GetValueRefOrAddDefault(_storages, address, out bool exists);
+ if (exists)
+ {
+ return storage;
+ }
+
+ Hash256 storageRoot = Get(address)?.StorageRoot ?? Keccak.EmptyTreeHash;
+ storage = new FlatStorageTree(
+ this,
+ _warmer,
+ _snapshotBundle,
+ _configuration,
+ _concurrencyQuota,
+ storageRoot,
+ address,
+ _logManager);
+
+ return storage;
+ }
+
+ public IWorldStateScopeProvider.IWorldStateWriteBatch StartWriteBatch(int estimatedAccountNum)
+ {
+ // Invalidates trie node warmer tasks at this point. Write batch already do things in parallel.
+ return new WriteBatch(this, estimatedAccountNum, _logManager.GetClassLogger());
+ }
+
+ public void Commit(long blockNumber)
+ {
+ StateId newStateId = new StateId(blockNumber, RootHash);
+ if (!_isReadOnly)
+ {
+ long sw = Stopwatch.GetTimestamp();
+ // Commit will copy the trie nodes from the tree to the bundle.
+ using ArrayPoolList commitTask = new ArrayPoolList(_storages.Count);
+
+ commitTask.Add(Task.Factory.StartNew(() =>
+ {
+ sw = Stopwatch.GetTimestamp();
+ // Commit will copy the trie nodes from the tree to the bundle.
+ _stateTree.Commit();
+ _snapshotBundleTimes.WithLabels("statetree_commit").Observe(Stopwatch.GetTimestamp() - sw);
+ }));
+
+ foreach (KeyValuePair storage in _storages)
+ {
+ commitTask.Add(Task.Factory.StartNew((ctx) =>
+ {
+ FlatStorageTree st = (FlatStorageTree)ctx;
+ st.CommitTree();
+ _concurrencyQuota.ReturnConcurrencyQuota();
+ }, storage.Value));
+ }
+
+ Task.WaitAll(commitTask.AsSpan());
+ _snapshotBundleTimes.WithLabels("storage_commit_wait").Observe(Stopwatch.GetTimestamp() - sw);
+ }
+
+ _storages.Clear();
+
+ bool shouldAddSnapshot = !_isReadOnly && _currentStateId != newStateId;
+
+ (Snapshot newSnapshot, CachedResource cachedResource) = _snapshotBundle.CollectAndApplySnapshot(_currentStateId, newStateId, shouldAddSnapshot);
+
+ if (shouldAddSnapshot)
+ {
+ if (_currentStateId != newStateId)
+ {
+ _flatDiffRepository.AddSnapshot(newSnapshot, cachedResource);
+ }
+ }
+
+ _currentStateId = newStateId;
+ }
+
+ private class WriteBatch(
+ FlatWorldStateScope scope,
+ int estimatedAccountCount,
+ ILogger logger
+ ) : IWorldStateScopeProvider.IWorldStateWriteBatch
+ {
+ private readonly Dictionary _dirtyAccounts = new(estimatedAccountCount);
+ private readonly ConcurrentQueue<(AddressAsKey, Hash256)> _dirtyStorageTree = new();
+
+ public event EventHandler? OnAccountUpdated;
+
+ public void Set(Address key, Account? account)
+ {
+ if (key == DebugAddress) Console.Error.WriteLine($"Address Set {account}");
+ _dirtyAccounts[key] = account;
+ scope._snapshotBundle.SetAccount(key, account);
+
+ if (account == null)
+ {
+ // This may not get called by the storage write batch as the worldstate does not try to update storage
+ // at all if the end account is null. This is not a problem for trie, but is a problem for flat.
+ scope.CreateStorageTreeImpl(key).SelfDestruct();
+ }
+ }
+
+ public IWorldStateScopeProvider.IStorageWriteBatch CreateStorageWriteBatch(Address address, int estimatedEntries)
+ {
+ return scope
+ .CreateStorageTreeImpl(address)
+ .CreateWriteBatch(
+ estimatedEntries: estimatedEntries,
+ onRootUpdated: (address, newRoot) => MarkDirty(address, newRoot));
+ }
+
+ private void MarkDirty(AddressAsKey address, Hash256 storageTreeRootHash)
+ {
+ _dirtyStorageTree.Enqueue((address, storageTreeRootHash));
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ long sw = Stopwatch.GetTimestamp();
+ while (_dirtyStorageTree.TryDequeue(out var entry))
+ {
+ (AddressAsKey key, Hash256 storageRoot) = entry;
+ if (!_dirtyAccounts.TryGetValue(key, out var account)) account = scope.Get(key);
+ if (account == null && storageRoot == Keccak.EmptyTreeHash) continue;
+ account ??= ThrowNullAccount(key);
+ account = account!.WithChangedStorageRoot(storageRoot);
+ // if (key == DebugAddress) Console.Error.WriteLine($"Address root update {account}");
+ scope._snapshotBundle.SetAccount(key, account);
+ _dirtyAccounts[key] = account;
+ OnAccountUpdated?.Invoke(key, new IWorldStateScopeProvider.AccountUpdated(key, account));
+ if (logger.IsTrace) Trace(key, storageRoot, account);
+ }
+ _snapshotBundleTimes.WithLabels("dirtystorage_dequeue").Observe(Stopwatch.GetTimestamp() - sw);
+
+ using (var stateSetter = scope._stateTree.BeginSet(_dirtyAccounts.Count))
+ {
+ sw = Stopwatch.GetTimestamp();
+ foreach (var kv in _dirtyAccounts)
+ {
+ stateSetter.Set(kv.Key, kv.Value);
+ }
+ _snapshotBundleTimes.WithLabels("account_set").Observe(Stopwatch.GetTimestamp() - sw);
+ sw = Stopwatch.GetTimestamp();
+ }
+ _snapshotBundleTimes.WithLabels("account_set_dispose").Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ finally
+ {
+ _dirtyAccounts.Clear();
+
+ Interlocked.Increment(ref scope._hintSequenceId);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ void Trace(Address address, Hash256 storageRoot, Account? account)
+ => logger.Trace($"Update {address} S {account?.StorageRoot} -> {storageRoot}");
+
+ [DoesNotReturn, StackTraceHidden]
+ static Account ThrowNullAccount(Address address)
+ => throw new InvalidOperationException($"Account {address} is null when updating storage hash");
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/StateTrieStoreAdapter.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/StateTrieStoreAdapter.cs
new file mode 100644
index 00000000000..ac23933808f
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/StateTrieStoreAdapter.cs
@@ -0,0 +1,75 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using Nethermind.Core;
+using Nethermind.Core.Crypto;
+using Nethermind.Trie;
+using Nethermind.Trie.Pruning;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+internal class StateTrieStoreAdapter(
+ SnapshotBundle bundle,
+ ConcurrencyQuota concurrencyQuota,
+ bool isTrieWarmer
+) : AbstractMinimalTrieStore
+{
+ public override TrieNode FindCachedOrUnknown(in TreePath path, Hash256 hash)
+ {
+ return bundle.FindStateNodeOrUnknown(path, hash, isTrieWarmer);
+ }
+
+ public override byte[]? TryLoadRlp(in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None) => bundle.TryLoadRlp(null, path, hash, flags, isTrieWarmer);
+
+ public override ICommitter BeginCommit(TrieNode? root, WriteFlags writeFlags = WriteFlags.None) => new Committer(bundle, concurrencyQuota);
+
+ public override ITrieNodeResolver GetStorageTrieNodeResolver(Hash256? address)
+ {
+ // Used in trie visitor and weird very edge case that cuts the whole thing to peaces
+ return new StorageTrieStoreAdapter(bundle, concurrencyQuota, address, -1, isTrieWarmer);
+ }
+
+ private class Committer(SnapshotBundle bundle, ConcurrencyQuota concurrencyQuota) : AbstractMinimalCommitter(concurrencyQuota)
+ {
+ public override TrieNode CommitNode(ref TreePath path, TrieNode node)
+ {
+ bundle.SetStateNode(path, node);
+ return node;
+ }
+ }
+}
+
+internal class StorageTrieStoreAdapter(
+ SnapshotBundle bundle,
+ ConcurrencyQuota concurrencyQuota,
+ Hash256AsKey addressHash,
+ int selfDestructKnownStateIdx,
+ bool isTrieWarmer
+): AbstractMinimalTrieStore
+{
+ internal int SelfDestructKnownStateIdx = selfDestructKnownStateIdx;
+
+ public override TrieNode FindCachedOrUnknown(in TreePath path, Hash256 hash)
+ {
+ return bundle.FindStorageNodeOrUnknown(addressHash, path, hash, SelfDestructKnownStateIdx, isTrieWarmer);
+ }
+
+ public override byte[]? TryLoadRlp(in TreePath path, Hash256 hash, ReadFlags flags = ReadFlags.None)
+ {
+ return bundle.TryLoadRlp(addressHash, in path, hash, flags, isTrieWarmer);
+ }
+
+ public override ICommitter BeginCommit(TrieNode? root, WriteFlags writeFlags = WriteFlags.None)
+ {
+ return new Committer(bundle, addressHash, concurrencyQuota);
+ }
+
+ private class Committer(SnapshotBundle bundle, Hash256AsKey addressHash, ConcurrencyQuota concurrencyQuota) : AbstractMinimalCommitter(concurrencyQuota)
+ {
+ public override TrieNode CommitNode(ref TreePath path, TrieNode node)
+ {
+ bundle.SetStorageNode(addressHash, path, node);
+ return node;
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/ScopeProvider/TrieStoreTrieCacheWarmer.cs b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/TrieStoreTrieCacheWarmer.cs
new file mode 100644
index 00000000000..6f58badc914
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/ScopeProvider/TrieStoreTrieCacheWarmer.cs
@@ -0,0 +1,253 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Nethermind.Config;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Int256;
+using Nethermind.Logging;
+using Nethermind.Trie;
+using Prometheus;
+
+namespace Nethermind.State.Flat.ScopeProvider;
+
+public interface ITrieWarmer
+{
+ public void PushJob(
+ FlatWorldStateScope scope,
+ Address? path,
+ FlatStorageTree? storageTree,
+ in UInt256? index,
+ int sequenceId);
+
+ void OnNewScope();
+}
+
+public class NoopTrieWarmer : ITrieWarmer
+{
+ public void PushJob(FlatWorldStateScope scope, Address? path, FlatStorageTree? storageTree, in UInt256? index, int sequenceId)
+ {
+ }
+
+ public void OnNewScope()
+ {
+ }
+}
+
+public sealed class TrieWarmer : ITrieWarmer
+{
+ private SpmcRingBuffer _jobBuffer = new SpmcRingBuffer(256);
+
+ // If path is not null, its an address warmup.
+ // if storage tree is not null, its a storage warmup.
+ // So this ideally need to be under 64 byte in size so that it fits within cache line
+ private record struct Job(
+ object scopeOrStorageTree,
+ Address? path,
+ UInt256 index,
+ int sequenceId);
+
+ Task? _warmerJob = null;
+ private static Counter _trieWarmEr = DevMetric.Factory.CreateCounter("triestore_trie_warmer", "hit rate", "type");
+ private static Counter.Child _bufferFull = _trieWarmEr.WithLabels("buffer_full");
+ private ConcurrentStack _awaitingWorkers = new ConcurrentStack();
+ private WarmerWorkers? _mainWarmer = null;
+
+ private bool TryDequeue(out Job job)
+ {
+ return _jobBuffer.TryDequeue(out job);
+ }
+
+ public TrieWarmer(IProcessExitSource processExitSource, ILogManager logManager)
+ {
+ int processorCount = Environment.ProcessorCount;
+ _warmerJob = Task.Run(async () =>
+ {
+ using ArrayPoolList tasks = new ArrayPoolList(processorCount);
+ for (int i = 0; i < processorCount; i++)
+ {
+ bool isMain = i == 0;
+ var worker = new WarmerWorkers(this, isMain);
+ tasks.Add(Task.Run(() =>
+ {
+ worker.Run(processExitSource.Token);
+ }));
+ }
+
+ await Task.WhenAll(tasks);;
+ });
+ }
+
+ private static void HandleJob(Job job, bool isMain)
+ {
+ (object scopeOrStorageTree,
+ Address? address,
+ UInt256 index,
+ int sequenceId) = job;
+
+ try
+ {
+ if (scopeOrStorageTree is FlatWorldStateScope scope)
+ {
+ if (scope.WarmUpStateTrie(address, sequenceId))
+ {
+ _trieWarmEr.WithLabels("state").Inc();
+ }
+ else
+ {
+ _trieWarmEr.WithLabels("state_skip").Inc();
+ }
+ }
+ else
+ {
+ FlatStorageTree storageTree = (FlatStorageTree)scopeOrStorageTree;
+ if (storageTree.WarUpStorageTrie(index, sequenceId))
+ {
+ _trieWarmEr.WithLabels("storage").Inc();
+ }
+ else
+ {
+ _trieWarmEr.WithLabels("storage_skip").Inc();
+ }
+ }
+ }
+ catch (TrieNodeException)
+ {
+ _trieWarmEr.WithLabels("err_trienode").Inc();
+ // It can be missing when the warmer lags so much behind that the node is now gone.
+ }
+ catch (ObjectDisposedException)
+ {
+ _trieWarmEr.WithLabels("err_disposed").Inc();
+ // Yea... this need to be fixed.
+ }
+ catch (NullReferenceException)
+ {
+ _trieWarmEr.WithLabels("err_null").Inc();
+ // Uhh....
+ }
+ }
+
+ private class WarmerWorkers(TrieWarmer mainWarmer, bool isMain)
+ {
+ private ManualResetEventSlim _resetEvent = new ManualResetEventSlim();
+ private SpinWait _spinWait = new SpinWait();
+
+ public void Run(CancellationToken cancellationToken)
+ {
+ try
+ {
+ while (true)
+ {
+ if (cancellationToken.IsCancellationRequested) break;
+
+ if (mainWarmer.TryDequeue(out var job))
+ {
+ _spinWait.Reset();
+ mainWarmer.MaybeWakeOpOtherWorker();
+
+ HandleJob(job, isMain);
+ }
+ else
+ {
+ if (_spinWait.NextSpinWillYield)
+ {
+ if (!isMain)
+ {
+ _trieWarmEr.WithLabels("wait_not_main").Inc();
+ _resetEvent.Reset();
+ mainWarmer.QueueWorker(this);
+
+ _resetEvent.Wait(1, cancellationToken);
+ }
+ else
+ {
+ _resetEvent.Reset();
+ mainWarmer.MainWarmerIdle(this);
+
+ _resetEvent.Wait(1, cancellationToken);
+ }
+
+ _spinWait.Reset();
+ }
+ else
+ {
+ _spinWait.SpinOnce();
+ }
+ }
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine("Error in warmup job " + ex);
+ }
+ }
+
+ public void WakeUp()
+ {
+ _resetEvent.Set();
+ }
+ }
+
+ private void MainWarmerIdle(WarmerWorkers warmerWorkers)
+ {
+ _mainWarmer = warmerWorkers;
+ }
+
+ private void MaybeWakeOpOtherWorker()
+ {
+ if (_jobBuffer.EstimatedJobCount > 0 && _awaitingWorkers.TryPop(out WarmerWorkers otherWorker)) otherWorker.WakeUp();
+ }
+
+ private void QueueWorker(WarmerWorkers worker)
+ {
+ _awaitingWorkers.Push(worker);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PushJob(
+ FlatWorldStateScope scope,
+ Address? path,
+ FlatStorageTree? storageTree,
+ in UInt256? index,
+ int sequenceId)
+ {
+ if (path is not null)
+ {
+ if (!_jobBuffer.TryEnqueue(new Job(scope, path, index.GetValueOrDefault(), sequenceId)))
+ {
+ _bufferFull.Inc();
+ return;
+ }
+ }
+ else
+ {
+ if (!_jobBuffer.TryEnqueue(new Job(storageTree, path, index.GetValueOrDefault(), sequenceId)))
+ {
+ _bufferFull.Inc();
+ return;
+ }
+ }
+
+ WarmerWorkers? mainWarmer = _mainWarmer;
+ if (mainWarmer is not null)
+ {
+ mainWarmer.WakeUp();
+ _mainWarmer = null;
+ }
+ }
+
+ public void OnNewScope()
+ {
+ _mainWarmer?.WakeUp();
+ _mainWarmer = null;
+ }
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/Snapshot.cs b/src/Nethermind/Nethermind.State/Flat/Snapshot.cs
new file mode 100644
index 00000000000..cde39b49ae4
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/Snapshot.cs
@@ -0,0 +1,147 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Microsoft.Extensions.ObjectPool;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Utils;
+using Nethermind.Int256;
+using Nethermind.Trie;
+
+namespace Nethermind.State.Flat;
+
+///
+/// Snapshot are written keys between state From to state To
+///
+///
+///
+///
+///
+public class Snapshot(
+ StateId from,
+ StateId to,
+ SnapshotContent content,
+ ObjectPool pool
+) : RefCountingDisposable
+{
+ private Dictionary? _memory = null; // The memory changes, so we use this as a smoewhat estimate so it make some seense
+ public Dictionary EstimateMemory() => _memory ??= content.EstimateMemory();
+
+ public StateId From => from;
+ public StateId To => to;
+ public IEnumerable> Accounts => content.Accounts;
+ public IEnumerable> SelfDestructedStorageAddresses => content.SelfDestructedStorageAddresses;
+ public IEnumerable> Storages => content.Storages;
+ public IEnumerable> StorageNodes => content.StorageNodes;
+ public IEnumerable<(Hash256AsKey, TreePath)> StorageTrieNodeKeys => content.StorageNodes.Keys;
+ public IEnumerable> StateNodes => content.StateNodes;
+ public IEnumerable StateNodeKeys => content.StateNodes.Keys;
+ public int AccountsCount => content.Accounts.Count;
+ public int StoragesCount => content.Storages.Count;
+ public int TrieNodesCount => content.StorageNodes.Count;
+ public long DebugLease => _leases.Value;
+
+ public bool TryGetAccount(AddressAsKey key, out Account acc)
+ {
+ return content.Accounts.TryGetValue(key, out acc);
+ }
+
+ public bool HasSelfDestruct(Address address)
+ {
+ return content.SelfDestructedStorageAddresses.TryGetValue(address, out var _);
+ }
+
+ public bool TryGetStorage(Address address, in UInt256 index, out byte[] value)
+ {
+ return content.Storages.TryGetValue((address, index), out value);
+ }
+
+ public bool TryGetStateNode(in TreePath path, out TrieNode node)
+ {
+ return content.StateNodes.TryGetValue(path, out node);
+ }
+
+ public bool TryGetStorageNode(Hash256 address, in TreePath path, out TrieNode node)
+ {
+ return content.StorageNodes.TryGetValue((address, path), out node);
+ }
+
+ protected override void CleanUp()
+ {
+ pool.Return(content);
+ }
+
+ public bool TryAcquire()
+ {
+ return TryAcquireLease();
+ }
+}
+
+public record SnapshotContent(
+ // They dont actually need to be concurrent, but its makes commit fast by just passing the whole content.
+ ConcurrentDictionary Accounts,
+ ConcurrentDictionary<(AddressAsKey, UInt256), byte[]?> Storages,
+
+ // Bool is true if this is a new account also
+ ConcurrentDictionary SelfDestructedStorageAddresses,
+
+ // Use of a separate dictionary just for state have a small but measurable impact
+ ConcurrentDictionary StateNodes,
+ ConcurrentDictionary<(Hash256AsKey, TreePath), TrieNode> StorageNodes
+) {
+ public void Reset()
+ {
+ Accounts.NoResizeClear();
+ Storages.NoResizeClear();
+ SelfDestructedStorageAddresses.NoResizeClear();
+ StateNodes.NoResizeClear();
+ StorageNodes.NoResizeClear();
+ }
+
+ public Dictionary EstimateMemory()
+ {
+ Dictionary result = new Dictionary(){
+ { MemoryType.Account, Accounts.Count },
+ { MemoryType.Storage, Storages.Count },
+ { MemoryType.StorageBytes, Storages.Sum((kv) => kv.Value?.Length ?? 0) },
+ { MemoryType.SelfDestructedAddress, SelfDestructedStorageAddresses.Count },
+ { MemoryType.StateNodes, StateNodes.Count },
+ { MemoryType.StateNodesBytes, StateNodes.Sum((kv) => kv.Value.GetMemorySize(false)) },
+ { MemoryType.StorageNodes, StorageNodes.Count },
+ { MemoryType.StorageNodesBytes, StorageNodes.Sum((kv) => kv.Value.GetMemorySize(false)) },
+ };
+
+ // I'm just winging it here.
+ result[MemoryType.TotalBytes]
+ = result[MemoryType.Account] * 40 +
+ result[MemoryType.Storage] * 48 +
+ result[MemoryType.StorageBytes] +
+ result[MemoryType.SelfDestructedAddress] * 40 +
+ result[MemoryType.StateNodes] * 40 +
+ result[MemoryType.StateNodesBytes] +
+ result[MemoryType.StorageNodes] * 48 +
+ result[MemoryType.StorageNodesBytes];
+
+ return result;
+ }
+}
+
+public enum MemoryType
+{
+ Account,
+ Storage,
+ StorageBytes,
+ SelfDestructedAddress,
+ StateNodes,
+ StateNodesBytes,
+ StorageNodes,
+ StorageNodesBytes,
+ TotalBytes
+}
diff --git a/src/Nethermind/Nethermind.State/Flat/SnapshotBundle.cs b/src/Nethermind/Nethermind.State/Flat/SnapshotBundle.cs
new file mode 100644
index 00000000000..1bbf829393a
--- /dev/null
+++ b/src/Nethermind/Nethermind.State/Flat/SnapshotBundle.cs
@@ -0,0 +1,779 @@
+// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Nethermind.Core;
+using Nethermind.Core.Collections;
+using Nethermind.Core.Crypto;
+using Nethermind.Core.Extensions;
+using Nethermind.Int256;
+using Nethermind.State.Flat.Persistence;
+using Nethermind.State.Flat.ScopeProvider;
+using Nethermind.Trie;
+using Prometheus;
+
+namespace Nethermind.State.Flat;
+
+///
+/// A bundle of and a layer of write buffer backed by a .
+///
+public class SnapshotBundle : IDisposable
+{
+ private SnapshotContent _currentPooledContent;
+ // These maps are direct reference from members in _currentPooledContent.
+ private ConcurrentDictionary _changedAccounts;
+ private ConcurrentDictionary _changedStateNodes; // Bulkset can get nodes concurrently
+ private ConcurrentDictionary<(Hash256AsKey, TreePath), TrieNode> _changedStorageNodes; // Bulkset can get nodes concurrently
+ private ConcurrentDictionary<(AddressAsKey, UInt256), byte[]> _changedSlots; // Bulkset can get nodes concurrently
+ private ConcurrentDictionary _selfDestructedAccountAddresses;
+
+ // The cached resource holds some items that is pooled.
+ // Notably it holds loaded caches from trie warmer.
+ private CachedResource _cachedResource;
+
+ private readonly bool _forStateReader;
+
+ public int SnapshotCount => _snapshots.Count;
+
+ internal ArrayPoolList _snapshots;
+ private readonly IPersistence.IPersistenceReader _persistenceReader;
+ private readonly TrieNodeCache _trieNodeCache;
+ private bool _isPrewarmer;
+ private bool _isDisposed;
+ private readonly ResourcePool _resourcePool;
+
+ private static Gauge _activeSnapshotBundle = DevMetric.Factory.CreateGauge("snapshot_bundle_active", "active", "usage");
+ private static Counter _creeatedSnapshotBundle = DevMetric.Factory.CreateCounter("snapshot_bundle_created", "created", "usage");
+ private static Counter _snapshotBundleEvents = DevMetric.Factory.CreateCounter("snapshot_bundle_evens", "event", "type", "is_prewarmer");
+ private Counter.Child _nodeGetChanged;
+ private Counter.Child _nodeGetSnapshots;
+ private Counter.Child _nodeGetTrieCache;
+ private Counter.Child _nodeGetMiss;
+ private Counter.Child _nodeGetSelfDestruct;
+
+ private static Histogram _snapshotBundleTimes = DevMetric.Factory.CreateHistogram("snapshot_bundle_times", "aha", new HistogramConfiguration()
+ {
+ LabelNames = new[] { "type", "is_prewarmer" },
+ Buckets = Histogram.PowersOfTenDividedBuckets(1, 12, 5)
+ });
+ private Histogram.Child _accountPersistenceRead;
+ private Histogram.Child _slotPersistenceRead;
+ private Histogram.Child _accountPersistenceEmptyRead;
+ private Histogram.Child _slotPersistenceEmptyRead;
+ private Histogram.Child _loadRlpRead;
+ private Histogram.Child _loadRlpReadTrieWarmer;
+ private Histogram.Child _loadStorageRlpRead;
+ private Histogram.Child _loadStorageRlpReadTrieWarmer;
+ private Histogram.Child _findStateNode;
+ private Histogram.Child _findStorageNodeLoadedNodes;
+ private Histogram.Child _findStorageNodeChangedNodes;
+ private Histogram.Child _findStorageNodeSnapshots;
+ private Histogram.Child _findStorageNodeNodeCache;
+ private Histogram.Child _findStorageNodeNodeCacheBefore;
+ private Histogram.Child _findStateNodeTrieWarmer;
+ private Histogram.Child _findStorageNode;
+ private Histogram.Child _findStorageNodeTrieWarmer;
+ private Histogram.Child _setStateNodesTime;
+ private Histogram.Child _setStorageNodesTime;
+ private Histogram.Child _setSlotTime;
+ private Histogram.Child _setSlotToZeroTime;
+ private Histogram.Child _setAccountTime;
+
+ private Counter.Child _accountGet;
+ private Counter.Child _slotGet;
+
+ private IFlatDiffRepository.SnapshotBundleUsage _usage;
+
+ public SnapshotBundle(ArrayPoolList snapshots,
+ IPersistence.IPersistenceReader persistenceReader,
+ TrieNodeCache trieNodeCache,
+ ResourcePool resourcePool,
+ IFlatDiffRepository.SnapshotBundleUsage usage,
+ bool isPrewarmer = false)
+ {
+ _snapshots = snapshots;
+ _persistenceReader = persistenceReader;
+ _trieNodeCache = trieNodeCache;
+ _resourcePool = resourcePool;
+ _isPrewarmer = isPrewarmer;
+ _forStateReader = usage == IFlatDiffRepository.SnapshotBundleUsage.StateReader;
+ _usage = usage;
+ _activeSnapshotBundle.WithLabels(_usage.ToString()).Inc();
+ _creeatedSnapshotBundle.WithLabels(_usage.ToString()).Inc();
+
+ SetupMetric();
+
+ if (!_forStateReader)
+ {
+ _currentPooledContent = resourcePool.GetSnapshotContent(usage);
+ _cachedResource = resourcePool.GetCachedResource(usage);
+
+ ExpandCurrentPooledContent();
+ }
+ }
+
+ private void ExpandCurrentPooledContent()
+ {
+ _changedAccounts = _currentPooledContent.Accounts;
+ _changedSlots = _currentPooledContent.Storages;
+ _changedStorageNodes = _currentPooledContent.StorageNodes;
+ _changedStateNodes = _currentPooledContent.StateNodes;
+ _selfDestructedAccountAddresses = _currentPooledContent.SelfDestructedStorageAddresses;
+ }
+
+ public void SetPrewarmer()
+ {
+ _isPrewarmer = true;
+ SetupMetric();
+ }
+
+ private void SetupMetric()
+ {
+ _nodeGetChanged = _snapshotBundleEvents.WithLabels("node_get_changed", _isPrewarmer.ToString());
+ _nodeGetSnapshots = _snapshotBundleEvents.WithLabels("node_get_snapshots", _isPrewarmer.ToString());
+ _nodeGetTrieCache = _snapshotBundleEvents.WithLabels("node_get_trie_cache", _isPrewarmer.ToString());
+ _nodeGetSelfDestruct = _snapshotBundleEvents.WithLabels("node_get_self_destruct", _isPrewarmer.ToString());
+ _nodeGetMiss = _snapshotBundleEvents.WithLabels("node_get_miss", _isPrewarmer.ToString());
+ _accountGet = _snapshotBundleEvents.WithLabels("account_get", _isPrewarmer.ToString());
+ _slotGet = _snapshotBundleEvents.WithLabels("slot_get", _isPrewarmer.ToString());
+
+ _accountPersistenceRead = _snapshotBundleTimes.WithLabels("account_persistence", _isPrewarmer.ToString());
+ _slotPersistenceRead = _snapshotBundleTimes.WithLabels("slot_persistence", _isPrewarmer.ToString());
+ _accountPersistenceEmptyRead = _snapshotBundleTimes.WithLabels("empty_account_persistence", _isPrewarmer.ToString());
+ _slotPersistenceEmptyRead = _snapshotBundleTimes.WithLabels("empty_slot_persistence", _isPrewarmer.ToString());
+ _loadRlpRead = _snapshotBundleTimes.WithLabels("rlp_read", _isPrewarmer.ToString());
+ _loadRlpReadTrieWarmer = _snapshotBundleTimes.WithLabels("rlp_read_trie_warmer", _isPrewarmer.ToString());
+ _loadStorageRlpRead = _snapshotBundleTimes.WithLabels("storage_rlp_read", _isPrewarmer.ToString());
+ _loadStorageRlpReadTrieWarmer = _snapshotBundleTimes.WithLabels("storage_rlp_read_trie_warmer", _isPrewarmer.ToString());
+ _findStateNode = _snapshotBundleTimes.WithLabels("find_state_node", _isPrewarmer.ToString());
+
+ _findStorageNodeLoadedNodes = _snapshotBundleTimes.WithLabels("find_storage_node_loaded_nodes", _isPrewarmer.ToString());
+ _findStorageNodeChangedNodes = _snapshotBundleTimes.WithLabels("find_storage_node_changed_nodes", _isPrewarmer.ToString());;
+ _findStorageNodeSnapshots = _snapshotBundleTimes.WithLabels("find_storage_node_snapshots", _isPrewarmer.ToString());;
+ _findStorageNodeNodeCache = _snapshotBundleTimes.WithLabels("find_storage_node_node_cache", _isPrewarmer.ToString());;
+ _findStorageNodeNodeCacheBefore = _snapshotBundleTimes.WithLabels("find_storage_node_node_cache_before", _isPrewarmer.ToString());;
+
+ _findStateNodeTrieWarmer = _snapshotBundleTimes.WithLabels("find_state_node_trie_warmer", _isPrewarmer.ToString());
+ _findStorageNode = _snapshotBundleTimes.WithLabels("find_storage_node", _isPrewarmer.ToString());
+ _findStorageNodeTrieWarmer = _snapshotBundleTimes.WithLabels("find_storage_node_trie_warmer", _isPrewarmer.ToString());
+ _setSlotTime = _snapshotBundleTimes.WithLabels("set_slot", _isPrewarmer.ToString());
+ _setSlotToZeroTime = _snapshotBundleTimes.WithLabels("set_slot_zero", _isPrewarmer.ToString());
+ _setAccountTime = _snapshotBundleTimes.WithLabels("set_account", _isPrewarmer.ToString());
+
+ _setStateNodesTime = _snapshotBundleTimes.WithLabels("set_state_nodes", _isPrewarmer.ToString());
+ _setStorageNodesTime = _snapshotBundleTimes.WithLabels("set_storage_nodes", _isPrewarmer.ToString());
+ }
+
+ public bool TryGetAccount(Address address, out Account? acc)
+ {
+ return DoTryGetAccount(address, false, out acc);
+ }
+
+ private bool DoTryGetAccount(Address address, bool excludeChanged, out Account? acc)
+ {
+ if (_isDisposed)
+ {
+ acc = null;
+ return false;
+ }
+
+ _accountGet.Inc();
+ if (!_forStateReader && !excludeChanged)
+ {
+ if (_changedAccounts.TryGetValue(address, out acc)) return true;
+ }
+
+ AddressAsKey key = address;
+
+ for (int i = _snapshots.Count - 1; i >= 0; i--)
+ {
+ if (_snapshots[i].TryGetAccount(key, out acc))
+ {
+ return true;
+ }
+ }
+
+ long sw = Stopwatch.GetTimestamp();
+ if (_persistenceReader.TryGetAccount(address, out acc))
+ {
+ if (acc is null)
+ {
+ _accountPersistenceEmptyRead.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _accountPersistenceRead.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ public int DetermineSelfDestructSnapshotIdx(Address address)
+ {
+ if (_selfDestructedAccountAddresses.ContainsKey(address))
+ {
+ return _snapshots.Count;
+ }
+
+ for (int i = _snapshots.Count - 1; i >= 0; i--)
+ {
+ if (_snapshots[i].HasSelfDestruct(address))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public bool TryGetSlot(Address address, in UInt256 index, int selfDestructStateIdx, out byte[] value)
+ {
+ if (_isDisposed)
+ {
+ value = null;
+ return false;
+ }
+
+ _slotGet.Inc();
+
+ if (!_forStateReader)
+ {
+ if (_changedSlots.TryGetValue((address, index), out value))
+ {
+ return true;
+ }
+ }
+
+ if (selfDestructStateIdx == _snapshots.Count)
+ {
+ _nodeGetSelfDestruct.Inc();
+ value = null;
+ return true;
+ }
+
+ for (int i = _snapshots.Count - 1; i >= 0; i--)
+ {
+ if (_snapshots[i].TryGetStorage(address, index, out value)) return true;
+
+ if (i <= selfDestructStateIdx)
+ {
+ value = null;
+ return true;
+ }
+ }
+
+ long sw = Stopwatch.GetTimestamp();
+ if (_persistenceReader.TryGetSlot(address, index, out value))
+ {
+ if (value is null || value.Length == 0 || Bytes.AreEqual(value, StorageTree.ZeroBytes))
+ {
+ _slotPersistenceEmptyRead.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _slotPersistenceRead.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ public void SetChangedSlot(AddressAsKey address, in UInt256 index, byte[] value)
+ {
+ if (_forStateReader) throw new InvalidOperationException("Read only snapshot bundle");
+ long sw = Stopwatch.GetTimestamp();
+ // Note: Hot path
+ _changedSlots[(address, index)] = value;
+ if (value is null || Bytes.AreEqual(value, StorageTree.ZeroBytes))
+ {
+ _setSlotToZeroTime.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _setSlotTime.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ }
+
+ public TrieNode FindStateNodeOrUnknown(in TreePath path, Hash256 hash, bool isTrieWarmer)
+ {
+ TrieNode node;
+ if (_forStateReader)
+ {
+ if (DoFindStateNodeExternal(path, hash, out node))
+ {
+ return node;
+ }
+ return new TrieNode(NodeType.Unknown, hash);
+ }
+
+ long sw = Stopwatch.GetTimestamp();
+
+ if (!isTrieWarmer)
+ {
+ // _changedStateNodes is really hot, so we dont touch it during prewarmer.
+ if (_changedStateNodes.TryGetValue(path, out node))
+ {
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ _nodeGetChanged.Inc();
+ return node;
+ }
+ }
+
+ if (_cachedResource.TrieWarmerLoadedNodes.TryGetValue(path, out node) && node.Keccak == hash)
+ {
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+
+ // if (!isTrieWarmer) _changedStateNodes.TryAdd(path, node);
+ _nodeGetChanged.Inc();
+ return node;
+ }
+
+ if (!DoFindStateNodeExternal(path, hash, out node))
+ {
+ // The map to holds the unknown nodes is different for trie warmer and the main tries. This prevent
+ // random invalid block.
+ node = _cachedResource.TrieWarmerLoadedNodes.GetOrAdd(path, new TrieNode(NodeType.Unknown, hash));
+ }
+ else
+ {
+ _cachedResource.TrieWarmerLoadedNodes.AddOrUpdate(path,
+ static (path, trieNode) => trieNode,
+ static (treePath, trieNode, newNode) => newNode,
+ node);
+ }
+
+ if (isTrieWarmer)
+ {
+ _findStateNodeTrieWarmer.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _findStateNode.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+
+ return node;
+ }
+
+ private bool DoFindStateNodeExternal(in TreePath path, Hash256 hash, out TrieNode node)
+ {
+ if (_isDisposed)
+ {
+ node = null;
+ return false;
+ }
+
+ if (_trieNodeCache.TryGet(null, path, hash, out node))
+ {
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ _nodeGetTrieCache.Inc();
+ return true;
+ }
+
+ for (int i = _snapshots.Count - 1; i >= 0; i--)
+ {
+ if (_snapshots[i].TryGetStateNode(path, out node))
+ {
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ _nodeGetSnapshots.Inc();
+ return true;
+ }
+ }
+
+ _nodeGetMiss.Inc();
+ return false;
+ }
+
+ public TrieNode FindStorageNodeOrUnknown(Hash256AsKey address, in TreePath path, Hash256 hash,
+ int selfDestructStateIdx, bool isTrieWarmer)
+ {
+ long sw = Stopwatch.GetTimestamp();
+ var res = DoFindStorageNodeOrUnknown(address, path, hash, selfDestructStateIdx, isTrieWarmer);
+
+ if (isTrieWarmer)
+ {
+ _findStorageNodeTrieWarmer.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _findStorageNode.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+
+ return res;
+ }
+
+ private TrieNode DoFindStorageNodeOrUnknown(Hash256AsKey address, in TreePath path, Hash256 hash, int selfDestructStateIdx, bool isTrieWarmer)
+ {
+ if (_isDisposed)
+ {
+ return new TrieNode(NodeType.Unknown, hash);
+ }
+
+ TrieNode node;
+ long sw = Stopwatch.GetTimestamp();
+
+ if (_forStateReader)
+ {
+ if (DoTryFindStorageNodeExternal(address, path, hash, selfDestructStateIdx, isTrieWarmer, sw, out node))
+ {
+ return node;
+ }
+ return new TrieNode(NodeType.Unknown, hash);
+ }
+
+ if (!isTrieWarmer)
+ {
+ if (_changedStorageNodes.TryGetValue((address, path), out node))
+ {
+ if (!isTrieWarmer) _findStorageNodeChangedNodes.Observe(Stopwatch.GetTimestamp() - sw);
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ return node;
+ }
+ }
+
+ if (_cachedResource.LoadedStorageNodes.TryGetValue((address, path), out node) && node.Keccak == hash)
+ {
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ if (!isTrieWarmer) _findStorageNodeLoadedNodes.Observe(Stopwatch.GetTimestamp() - sw);
+ // if (!isTrieWarmer) _changedStorageNodes.TryAdd((address, path), node);
+ return node;
+ }
+
+ if (!DoTryFindStorageNodeExternal(address, path, hash, selfDestructStateIdx, isTrieWarmer, sw, out node))
+ {
+ node = _cachedResource.LoadedStorageNodes.GetOrAdd((address, path), new TrieNode(NodeType.Unknown, hash));
+ }
+ else
+ {
+ _cachedResource.LoadedStorageNodes.AddOrUpdate((address, path),
+ static (key, param) => param,
+ static (key, originalValue, param) => param,
+ node);
+ }
+
+ return node;
+ }
+
+ private bool DoTryFindStorageNodeExternal(Hash256AsKey address, in TreePath path, Hash256 hash, int selfDestructStateIdx, bool isTrieWarmer, long sw, out TrieNode node)
+ {
+ if (selfDestructStateIdx == -1)
+ {
+ // If no self destruct idx, check node cache first
+ if (_trieNodeCache.TryGet(address, path, hash, out node))
+ {
+ if (!isTrieWarmer) _findStorageNodeNodeCache.Observe(Stopwatch.GetTimestamp() - sw);
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ _nodeGetTrieCache.Inc();
+ return true;
+ }
+ }
+
+ for (int i = _snapshots.Count - 1; i >= 0 && i >= selfDestructStateIdx; i--)
+ {
+ if (_snapshots[i].TryGetStorageNode(address, path, out node))
+ {
+ if (!isTrieWarmer) _findStorageNodeSnapshots.Observe(Stopwatch.GetTimestamp() - sw);
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ _nodeGetSnapshots.Inc();
+ return true;
+ }
+ }
+
+ if (selfDestructStateIdx != -1)
+ {
+ // If there is a self destruct, there is no need to check further, return true
+ Nethermind.Trie.Pruning.Metrics.LoadedFromCacheNodesCount++;
+ _nodeGetSelfDestruct.Inc();
+ node = null;
+ return true;
+ }
+
+ _nodeGetMiss.Inc();
+ node = null;
+ return false;
+ }
+
+ public byte[]? TryLoadRlp(Hash256? address, in TreePath path, Hash256 hash, ReadFlags flags, bool isTrieWarmer)
+ {
+ if (_isDisposed) return null;
+ Nethermind.Trie.Pruning.Metrics.LoadedFromDbNodesCount++;
+ long sw = Stopwatch.GetTimestamp();
+ var res = _persistenceReader.TryLoadRlp(address, path, hash, flags);
+ if (isTrieWarmer)
+ {
+ if (address is null)
+ {
+ _loadRlpReadTrieWarmer.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _loadStorageRlpReadTrieWarmer.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ }
+ else
+ {
+ if (address is null)
+ {
+ _loadRlpRead.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ else
+ {
+ _loadStorageRlpRead.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+ }
+ return res;
+ }
+
+ // This is called only during trie commit
+ public void SetStateNode(in TreePath path, TrieNode newNode)
+ {
+ if (_forStateReader) throw new InvalidOperationException("Read only snapshot bundle");
+ if (_isDisposed) return;
+ if (!newNode.IsSealed) throw new Exception("Node must be sealed for setting");
+
+ long sw = Stopwatch.GetTimestamp();
+ // Note: Hot path
+ _changedStateNodes[path] = newNode;
+ _setStateNodesTime.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+
+ // This is called only during trie commit
+ public void SetStorageNode(Hash256AsKey addr, in TreePath path, TrieNode newNode)
+ {
+ if (_forStateReader) throw new InvalidOperationException("Read only snapshot bundle");
+ if (_isDisposed) return;
+ if (!newNode.IsSealed) throw new Exception("Node must be sealed for setting");
+
+ long sw = Stopwatch.GetTimestamp();
+ // Note: Hot path
+ _changedStorageNodes[(addr, path)] = newNode;
+ _setStorageNodesTime.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+
+ public void SetAccount(AddressAsKey addr, Account? account)
+ {
+ if (addr == FlatWorldStateScope.DebugAddress)
+ {
+ Console.Error.WriteLine($"set to {account}");
+ }
+ long sw = Stopwatch.GetTimestamp();
+ _changedAccounts[addr] = account;
+ _setAccountTime.Observe(Stopwatch.GetTimestamp() - sw);
+ }
+
+ public bool ShouldPrewarm(Address address, UInt256? slot)
+ {
+ return _cachedResource.PrewarmedAddresses.TryAdd((address, slot), true);
+ }
+
+ public (Snapshot, CachedResource) CollectAndApplySnapshot(StateId from, StateId to, bool returnSnapshot = true)
+ {
+ if (_forStateReader) throw new InvalidOperationException("Read only snapshot bundle");
+
+ // When assembling the snapshot, we straight up pass the _currentPooledContent into the new snapshot
+ // This is because copying the values have a measurable impact on overall performance.
+ var snapshot = new Snapshot(
+ from: from,
+ to: to,
+ content: _currentPooledContent,
+ pool: _resourcePool.GetSnapshotPool(_usage));
+
+ snapshot.AcquireLease(); // For this SnapshotBundle.
+ _snapshots.Add(snapshot); // Now later reads are correct
+
+ // Invalidate cached resources
+ if (returnSnapshot)
+ {
+ CachedResource cachedResource = _cachedResource;
+ _cachedResource = _resourcePool.GetCachedResource(_usage);
+
+ // Make and apply new snapshot content.
+ _currentPooledContent = _resourcePool.GetSnapshotContent(_usage);
+ ExpandCurrentPooledContent();
+
+ return (snapshot, cachedResource);
+ }
+ else
+ {
+ snapshot.Dispose(); // Revert the lease before
+
+ _cachedResource.Clear();
+ _currentPooledContent = _resourcePool.GetSnapshotContent(_usage);
+
+ return (null, null);
+ }
+ }
+
+ public Snapshot CompactToKnownState()
+ {
+ // TODO: Get this out of here. It feels weird.
+ if (_snapshots.Count == 0)
+ return new Snapshot(
+ new StateId(-1, ValueKeccak.EmptyTreeHash), new StateId(-1, ValueKeccak.EmptyTreeHash),
+ content: _resourcePool.GetSnapshotContent(_usage),
+ pool: _resourcePool.GetSnapshotPool(IFlatDiffRepository.SnapshotBundleUsage.Compactor));
+
+ SnapshotContent content = _resourcePool.GetSnapshotContent(IFlatDiffRepository.SnapshotBundleUsage.Compactor);
+
+ ConcurrentDictionary accounts = content.Accounts;
+ ConcurrentDictionary<(AddressAsKey, UInt256), byte[]> storages = content.Storages;
+ ConcurrentDictionary