Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/debug get bad blocks #3838

Merged
merged 24 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2827e52
Added debug_getBadBlocks implementation.
kjazgar Feb 17, 2022
cfb4c4d
Added method implementation.
kjazgar Feb 18, 2022
c6b7d11
Added test.
kjazgar Feb 21, 2022
4665b25
Added logger with first invalid block information.
kjazgar Mar 14, 2022
8351e82
remove rlp logging
LukaszRozmej Mar 25, 2022
f947e72
remove merge markers
Nov 7, 2023
43b0ede
update old PR so it compiles
Nov 9, 2023
86bd281
cleanup test
Nov 10, 2023
a9fbbd1
cleanup and use BlockTreeBuilder
Nov 16, 2023
d31a48a
Remove one ToArray
LukaszRozmej Nov 27, 2023
ebb12ec
fix whitespace
Marchhill Nov 27, 2023
bf40f5e
persist bad blocks to disk
Marchhill Dec 4, 2023
88aa8f0
Merge branch 'feature/debug_getBadBlocks' of github.com:NethermindEth…
Marchhill Dec 4, 2023
451eb1e
fix benchmarks
Marchhill Dec 7, 2023
49f0c00
convert Block arrays to IEnumerable<Block>
Marchhill Dec 11, 2023
a41ae7d
limit size of bad blocks db
Marchhill Dec 11, 2023
0320ed4
make number of bad blocks stored configurable
Marchhill Dec 11, 2023
1f23635
delete oldest blocks
Marchhill Dec 11, 2023
5d0635a
remove GetInvalidBlocks from BlockTree
LukaszRozmej Dec 12, 2023
0e5724c
respond to comments
Marchhill Dec 12, 2023
43b521d
Merge branch 'feature/debug_getBadBlocks_refactor' of github.com:Neth…
Marchhill Dec 12, 2023
4ea54c5
Merge branch 'master' of github.com:NethermindEth/nethermind into fea…
Marchhill Dec 12, 2023
ddc220e
fix test
Marchhill Dec 12, 2023
b6a9e64
Merge remote-tracking branch 'upstream/master' into feature/debug_get…
Marchhill Jan 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Api/IApiWithStores.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using Nethermind.Blockchain;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.Receipts;
using Nethermind.Consensus;
Expand All @@ -27,5 +28,6 @@ public interface IApiWithStores : IBasicApi
IReceiptFinder? ReceiptFinder { get; set; }
IReceiptMonitor? ReceiptMonitor { get; set; }
IWallet? Wallet { get; set; }
IBlockStore? BadBlocksStore { get; set; }
}
}
3 changes: 3 additions & 0 deletions src/Nethermind/Nethermind.Api/IInitConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public interface IInitConfig : IConfig
[ConfigItem(Description = "The hint on the max memory limit, in bytes, to configure the database and networking memory allocations.", DefaultValue = "null")]
long? MemoryHint { get; set; }

[ConfigItem(Description = "The maximum number of bad blocks observed on the network that will be stored to disk.", DefaultValue = "100")]
long? BadBlocksStored { get; set; }

[ConfigItem(Description = "[TECHNICAL] Disable garbage collector on newPayload", DefaultValue = "true", HiddenFromDocs = true)]
bool DisableGcOnNewPayload { get; set; }

Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Api/InitConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class InitConfig : IInitConfig

public string RpcDbUrl { get; set; } = String.Empty;
public long? MemoryHint { get; set; }
public long? BadBlocksStored { get; set; } = 100;
public bool DisableGcOnNewPayload { get; set; } = true;
public bool DisableMallocOpts { get; set; } = false;
public long? ExitOnBlockNumber { get; set; } = null;
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Api/NethermindApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Nethermind.Abi;
using Nethermind.Api.Extensions;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Filters;
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.FullPruning;
Expand Down Expand Up @@ -210,6 +211,7 @@ public ISealEngine SealEngine
public IEthSyncingInfo? EthSyncingInfo { get; set; }
public IBlockProductionPolicy? BlockProductionPolicy { get; set; }
public IWallet? Wallet { get; set; }
public IBlockStore? BadBlocksStore { get; set; }
public ITransactionComparerProvider? TransactionComparerProvider { get; set; }
public IWebSocketsManager WebSocketsManager { get; set; } = new WebSocketsManager();

Expand Down
4 changes: 4 additions & 0 deletions src/Nethermind/Nethermind.Blockchain/BlockTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public partial class BlockTree : IBlockTree
private readonly IHeaderStore _headerStore;
private readonly IDb _blockInfoDb;
private readonly IDb _metadataDb;
private readonly IBlockStore _badBlockStore;

private readonly LruCache<ValueHash256, Block> _invalidBlocks =
new(128, 128, "invalid blocks");
Expand Down Expand Up @@ -110,6 +111,7 @@ public partial class BlockTree : IBlockTree
IHeaderStore? headerDb,
IDb? blockInfoDb,
IDb? metadataDb,
IBlockStore? badBlockStore,
IChainLevelInfoRepository? chainLevelInfoRepository,
ISpecProvider? specProvider,
IBloomStorage? bloomStorage,
Expand All @@ -121,6 +123,7 @@ public partial class BlockTree : IBlockTree
_headerStore = headerDb ?? throw new ArgumentNullException(nameof(headerDb));
_blockInfoDb = blockInfoDb ?? throw new ArgumentNullException(nameof(blockInfoDb));
_metadataDb = metadataDb ?? throw new ArgumentNullException(nameof(metadataDb));
_badBlockStore = badBlockStore ?? throw new ArgumentNullException(nameof(badBlockStore));
_specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider));
_bloomStorage = bloomStorage ?? throw new ArgumentNullException(nameof(bloomStorage));
_syncConfig = syncConfig ?? throw new ArgumentNullException(nameof(syncConfig));
Expand Down Expand Up @@ -710,6 +713,7 @@ public void DeleteInvalidBlock(Block invalidBlock)
if (_logger.IsDebug) _logger.Debug($"Deleting invalid block {invalidBlock.ToString(Block.Format.FullHashAndNumber)}");

_invalidBlocks.Set(invalidBlock.Hash, invalidBlock);
_badBlockStore.Insert(invalidBlock);

BestSuggestedHeader = Head?.Header;
BestSuggestedBody = Head;
Expand Down
28 changes: 27 additions & 1 deletion src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using Nethermind.Core;
using Nethermind.Core.Caching;
using Nethermind.Core.Crypto;
Expand All @@ -20,10 +22,12 @@ public class BlockStore : IBlockStore

private readonly LruCache<ValueHash256, Block>
_blockCache = new(CacheSize, CacheSize, "blocks");
private long? _maxSize;

public BlockStore(IDb blockDb)
public BlockStore(IDb blockDb, long? maxSize = null)
{
_blockDb = blockDb;
_maxSize = maxSize;
}

public void SetMetadata(byte[] key, byte[] value)
Expand All @@ -36,6 +40,18 @@ public void SetMetadata(byte[] key, byte[] value)
return _blockDb.Get(key);
}

private void TruncateToMaxSize()
{
int toDelete = (int)(_blockDb.GetSize() - _maxSize!);
if (toDelete > 0)
{
foreach (var blockToDelete in GetAll().Take(toDelete))
{
Delete(blockToDelete.Number, blockToDelete.Hash);
}
}
}

public void Insert(Block block, WriteFlags writeFlags = WriteFlags.None)
{
if (block.Hash is null)
Expand All @@ -48,6 +64,11 @@ public void Insert(Block block, WriteFlags writeFlags = WriteFlags.None)
using NettyRlpStream newRlp = _blockDecoder.EncodeToNewNettyStream(block);

_blockDb.Set(block.Number, block.Hash, newRlp.AsSpan(), writeFlags);

if (_maxSize is not null)
{
TruncateToMaxSize();
}
}

private static void GetBlockNumPrefixedKey(long blockNumber, Hash256 blockHash, Span<byte> output)
Expand Down Expand Up @@ -88,4 +109,9 @@ public void Cache(Block block)
{
_blockCache.Set(block.Hash, block);
}

public IEnumerable<Block> GetAll()
{
return _blockDb.GetAllValues(true).Select(bytes => _blockDecoder.Decode(bytes.AsRlpStream()));
}
}
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Serialization.Rlp;
Expand All @@ -16,6 +17,7 @@ public interface IBlockStore
void Insert(Block block, WriteFlags writeFlags = WriteFlags.None);
void Delete(long blockNumber, Hash256 blockHash);
Block? Get(long blockNumber, Hash256 blockHash, bool shouldCache = true);
IEnumerable<Block> GetAll();
ReceiptRecoveryBlock? GetReceiptRecoveryBlock(long blockNumber, Hash256 blockHash);
void Cache(Block block);

Expand Down
27 changes: 27 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public BlockTreeBuilder(Block genesisBlock, ISpecProvider specProvider)
BlockNumbersDb = new TestMemDb();
BlockInfoDb = new TestMemDb();
MetadataDb = new TestMemDb();
BadBlocksDb = new TestMemDb();

_genesisBlock = genesisBlock;
_specProvider = specProvider;
Expand Down Expand Up @@ -79,6 +80,7 @@ public BlockTree BlockTree
HeaderStore,
BlockInfoDb,
MetadataDb,
BadBlockStore,
ChainLevelInfoRepository,
_specProvider,
BloomStorage,
Expand All @@ -105,6 +107,7 @@ protected override void BeforeReturn()
public ISyncConfig SyncConfig { get; set; } = new SyncConfig();

public IDb BlocksDb { get; set; }
public IDb BadBlocksDb { get; set; }

private IBlockStore? _blockStore;
public IBlockStore BlockStore
Expand Down Expand Up @@ -139,6 +142,18 @@ public IHeaderStore HeaderStore

public IDb MetadataDb { get; set; }

private IBlockStore? _badBlockStore;
public IBlockStore BadBlockStore
{
get
{
return _badBlockStore ??= new BlockStore(BadBlocksDb, 100);
}
set
{
_badBlockStore = value;
}
}
private IChainLevelInfoRepository? _chainLevelInfoRepository;

public IChainLevelInfoRepository ChainLevelInfoRepository
Expand Down Expand Up @@ -384,6 +399,18 @@ public BlockTreeBuilder WithBlockStore(IBlockStore blockStore)
return this;
}

public BlockTreeBuilder WithBadBlockStore(IBlockStore blockStore)
{
BadBlockStore = blockStore;
return this;
}

public BlockTreeBuilder WithHeaderStore(IHeaderStore headerStore)
{
HeaderStore = headerStore;
return this;
}

public BlockTreeBuilder WithBlocksDb(IDb blocksDb)
{
BlocksDb = blocksDb;
Expand Down
14 changes: 14 additions & 0 deletions src/Nethermind/Nethermind.Core/Caching/LruCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Nethermind.Core.Extensions;
using Nethermind.Core.Threading;

Expand Down Expand Up @@ -146,6 +147,19 @@ public bool Contains(TKey key)
return array;
}

[MethodImpl(MethodImplOptions.Synchronized)]
public TValue[] GetValues()
{
int i = 0;
TValue[] array = new TValue[_cacheMap.Count];
foreach (KeyValuePair<TKey, LinkedListNode<LruCacheItem>> kvp in _cacheMap)
{
array[i++] = kvp.Value.Value.Value;
}

return array;
}

private void Replace(TKey key, TValue value)
{
LinkedListNode<LruCacheItem>? node = _leastRecentlyUsed;
Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Db/DbNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static class DbNames
public const string BlockNumbers = "blockNumbers";
public const string Receipts = "receipts";
public const string BlockInfos = "blockInfos";
public const string BadBlocks = "badBlocks";
public const string Bloom = "bloom";
public const string Witness = "witness";
public const string CHT = "canonicalHashTrie";
Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Db/IDbProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public interface IDbProvider : IDisposable
public IDb HeadersDb => GetDb<IDb>(DbNames.Headers);
public IDb BlockNumbersDb => GetDb<IDb>(DbNames.BlockNumbers);
public IDb BlockInfosDb => GetDb<IDb>(DbNames.BlockInfos);
public IDb BadBlocksDb => GetDb<IDb>(DbNames.BadBlocks);

// BloomDB progress / config (does not contain blooms - they are kept in bloom storage)
public IDb BloomDb => GetDb<IDb>(DbNames.Bloom);
Expand Down
8 changes: 8 additions & 0 deletions src/Nethermind/Nethermind.Db/Metrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ public static class Metrics
[Description("Number of Metadata DB writes.")]
public static long MetadataDbWrites { get; set; }

[CounterMetric]
[Description("Number of BadBlocks DB writes.")]
public static long BadBlocksDbWrites { get; set; }

[CounterMetric]
[Description("Number of BadBlocks DB reads.")]
public static long BadBlocksDbReads { get; set; }

[CounterMetric]
[Description("Number of BlobTransactions DB reads.")]
public static long BlobTransactionsDbReads { get; set; }
Expand Down
1 change: 1 addition & 0 deletions src/Nethermind/Nethermind.Db/StandardDbInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ private void RegisterAll(bool useReceiptsDb, bool useBlobsDb)
RegisterDb(BuildRocksDbSettings(DbNames.Headers, () => Metrics.HeaderDbReads++, () => Metrics.HeaderDbWrites++));
RegisterDb(BuildRocksDbSettings(DbNames.BlockNumbers, () => Metrics.BlockNumberDbReads++, () => Metrics.BlockNumberDbWrites++));
RegisterDb(BuildRocksDbSettings(DbNames.BlockInfos, () => Metrics.BlockInfosDbReads++, () => Metrics.BlockInfosDbWrites++));
RegisterDb(BuildRocksDbSettings(DbNames.BadBlocks, () => Metrics.BadBlocksDbReads++, () => Metrics.BadBlocksDbWrites++));

RocksDbSettings stateDbSettings = BuildRocksDbSettings(DbNames.State, () => Metrics.StateDbReads++, () => Metrics.StateDbWrites++);
RegisterCustomDb(DbNames.State, () => new FullPruningDb(
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ public Task Execute(CancellationToken cancellationToken)

IBlockStore blockStore = new BlockStore(_get.DbProvider.BlocksDb);
IHeaderStore headerStore = new HeaderStore(_get.DbProvider.HeadersDb, _get.DbProvider.BlockNumbersDb);
IBlockStore badBlockStore = _set.BadBlocksStore = new BlockStore(_get.DbProvider.BadBlocksDb, initConfig.BadBlocksStored);

IBlockTree blockTree = _set.BlockTree = new BlockTree(
blockStore,
headerStore,
_get.DbProvider.BlockInfosDb,
_get.DbProvider.MetadataDb,
badBlockStore,
chainLevelInfoRepository,
_get.SpecProvider,
bloomStorage,
Expand Down
2 changes: 2 additions & 0 deletions src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ public virtual async Task Execute(CancellationToken cancellationToken)
if (_api.KeyStore is null) throw new StepDependencyException(nameof(_api.KeyStore));
if (_api.PeerPool is null) throw new StepDependencyException(nameof(_api.PeerPool));
if (_api.WitnessRepository is null) throw new StepDependencyException(nameof(_api.WitnessRepository));
if (_api.BadBlocksStore is null) throw new StepDependencyException(nameof(_api.BadBlocksStore));

ProofModuleFactory proofModuleFactory = new(_api.WorldStateManager, _api.BlockTree, _api.BlockPreprocessor, _api.ReceiptFinder, _api.SpecProvider, _api.LogManager);
rpcModuleProvider.RegisterBounded(proofModuleFactory, 2, rpcConfig.Timeout);
Expand All @@ -133,6 +134,7 @@ public virtual async Task Execute(CancellationToken cancellationToken)
_api.ConfigProvider,
_api.SpecProvider,
_api.SyncModeSelector,
_api.BadBlocksStore,
_api.FileSystem,
_api.LogManager);
rpcModuleProvider.RegisterBoundedByCpuCount(debugModuleFactory, rpcConfig.Timeout);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public void GlobalSetup()
new HeaderStore(dbProvider.HeadersDb, dbProvider.BlockNumbersDb),
dbProvider.BlockInfosDb,
dbProvider.MetadataDb,
new BlockStore(dbProvider.BadBlocksDb),
chainLevelInfoRepository,
specProvider,
NullBloomStorage.Instance,
Expand Down