Skip to content

Commit

Permalink
Implement debug_standardTraceBadBlockToFile method (NethermindEth#7278
Browse files Browse the repository at this point in the history
)
  • Loading branch information
rubo committed Jul 24, 2024
1 parent 93298ae commit f671118
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/Nethermind/Nethermind.Consensus/Tracing/GethStyleTracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Linq;
using System.Threading;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.Receipts;
using Nethermind.Consensus.Processing;
Expand All @@ -27,6 +28,7 @@ namespace Nethermind.Consensus.Tracing;

public class GethStyleTracer : IGethStyleTracer
{
private readonly IBlockStore _badBlockStore;
private readonly IBlockTree _blockTree;
private readonly ISpecProvider _specProvider;
private readonly ChangeableTransactionProcessorAdapter _transactionProcessorAdapter;
Expand All @@ -39,6 +41,7 @@ public GethStyleTracer(IBlockchainProcessor processor,
IWorldState worldState,
IReceiptStorage receiptStorage,
IBlockTree blockTree,
IBlockStore badBlockStore,
ISpecProvider specProvider,
ChangeableTransactionProcessorAdapter transactionProcessorAdapter,
IFileSystem fileSystem)
Expand All @@ -47,6 +50,7 @@ public GethStyleTracer(IBlockchainProcessor processor,
_worldState = worldState;
_receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage));
_blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
_badBlockStore = badBlockStore ?? throw new ArgumentNullException(nameof(badBlockStore));
_specProvider = specProvider;
_transactionProcessorAdapter = transactionProcessorAdapter;
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
Expand All @@ -55,7 +59,7 @@ public GethStyleTracer(IBlockchainProcessor processor,
public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions options, CancellationToken cancellationToken)
{
Block block = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.None);
if (block is null) throw new InvalidOperationException("Only historical blocks");
if (block is null) throw new InvalidOperationException($"No historical block found for {blockHash}");

if (txIndex > block.Transactions.Length - 1) throw new InvalidOperationException($"Block {blockHash} has only {block.Transactions.Length} transactions and the requested tx index was {txIndex}");

Expand Down Expand Up @@ -106,7 +110,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op
public GethLikeTxTrace? Trace(long blockNumber, int txIndex, GethTraceOptions options, CancellationToken cancellationToken)
{
Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical);
if (block is null) throw new InvalidOperationException("Only historical blocks");
if (block is null) throw new InvalidOperationException($"No historical block found for {blockNumber}");

if (txIndex > block.Transactions.Length - 1) throw new InvalidOperationException($"Block {blockNumber} has only {block.Transactions.Length} transactions and the requested tx index was {txIndex}");

Expand All @@ -116,7 +120,7 @@ public GethLikeTxTrace Trace(Hash256 blockHash, int txIndex, GethTraceOptions op
public GethLikeTxTrace? Trace(long blockNumber, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken)
{
Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical);
if (block is null) throw new InvalidOperationException("Only historical blocks");
if (block is null) throw new InvalidOperationException($"No historical block found for {blockNumber}");
if (tx.Hash is null) throw new InvalidOperationException("Cannot trace transactions without tx hash set.");

block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx));
Expand Down Expand Up @@ -150,7 +154,7 @@ public IEnumerable<string> TraceBlockToFile(Hash256 blockHash, GethTraceOptions
ArgumentNullException.ThrowIfNull(blockHash);
ArgumentNullException.ThrowIfNull(options);

var block = _blockTree.FindBlock(blockHash) ?? throw new InvalidOperationException("Only historical blocks");
var block = _blockTree.FindBlock(blockHash) ?? throw new InvalidOperationException($"No historical block found for {blockHash}");

if (!block.IsGenesis)
{
Expand All @@ -167,6 +171,24 @@ public IEnumerable<string> TraceBlockToFile(Hash256 blockHash, GethTraceOptions
return tracer.FileNames;
}

public IEnumerable<string> TraceBadBlockToFile(Hash256 blockHash, GethTraceOptions options, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(blockHash);
ArgumentNullException.ThrowIfNull(options);

var block = _badBlockStore
.GetAll()
.Where(b => b.Hash == blockHash)
.FirstOrDefault()
?? throw new InvalidOperationException($"No historical block found for {blockHash}");

var tracer = new GethLikeBlockFileTracer(block, options, _fileSystem);

_processor.Process(block, ProcessingOptions.Trace, tracer.WithCancellation(cancellationToken));

return tracer.FileNames;
}

private GethLikeTxTrace? Trace(Block block, Hash256? txHash, CancellationToken cancellationToken, GethTraceOptions options)
{
ArgumentNullException.ThrowIfNull(txHash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ public interface IGethStyleTracer
IReadOnlyCollection<GethLikeTxTrace> TraceBlock(BlockParameter blockParameter, GethTraceOptions options, CancellationToken cancellationToken);
IReadOnlyCollection<GethLikeTxTrace> TraceBlock(Rlp blockRlp, GethTraceOptions options, CancellationToken cancellationToken);
IEnumerable<string> TraceBlockToFile(Hash256 blockHash, GethTraceOptions options, CancellationToken cancellationToken);
IEnumerable<string> TraceBadBlockToFile(Hash256 blockHash, GethTraceOptions options, CancellationToken cancellationToken);
}
19 changes: 19 additions & 0 deletions src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,25 @@ static IEnumerable<string> GetFileNames(Hash256 hash) =>
actual.Should().BeEquivalentTo(expected);
}

[Test]
public void StandardTraceBadBlockToFile()
{
var blockHash = Keccak.EmptyTreeHash;

static IEnumerable<string> GetFileNames(Hash256 hash) =>
new[] { $"block_{hash.ToShortString()}-0", $"block_{hash.ToShortString()}-1" };

debugBridge
.TraceBadBlockToFile(Arg.Is(blockHash), Arg.Any<CancellationToken>(), Arg.Any<GethTraceOptions>())
.Returns(c => GetFileNames(c.ArgAt<Hash256>(0)));

var rpcModule = new DebugRpcModule(LimboLogs.Instance, debugBridge, jsonRpcConfig, specProvider);
var actual = rpcModule.debug_standardTraceBadBlockToFile(blockHash);
var expected = ResultWrapper<IEnumerable<string>>.Success(GetFileNames(blockHash));

actual.Should().BeEquivalentTo(expected);
}

[Test]
public void TraceBlockByHash_Success()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,10 @@ public IEnumerable<string> TraceBlockToFile(
CancellationToken cancellationToken,
GethTraceOptions? gethTraceOptions = null) =>
_tracer.TraceBlockToFile(blockHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken);

public IEnumerable<string> TraceBadBlockToFile(
Hash256 blockHash,
CancellationToken cancellationToken,
GethTraceOptions? gethTraceOptions = null) =>
_tracer.TraceBadBlockToFile(blockHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public override IDebugRpcModule Create()
scope.WorldState,
_receiptStorage,
_blockTree,
_badBlockStore,
_specProvider,
transactionProcessorAdapter,
_fileSystem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,18 @@ public ResultWrapper<IEnumerable<string>> debug_standardTraceBlockToFile(Hash256
return ResultWrapper<IEnumerable<string>>.Success(files);
}

public ResultWrapper<IEnumerable<string>> debug_standardTraceBadBlockToFile(Hash256 blockHash, GethTraceOptions options = null)
{
using var cancellationTokenSource = new CancellationTokenSource(_traceTimeout);
var cancellationToken = cancellationTokenSource.Token;

var files = _debugBridge.TraceBadBlockToFile(blockHash, cancellationToken, options);

if (_logger.IsTrace) _logger.Trace($"{nameof(debug_standardTraceBadBlockToFile)} request {blockHash}, result: {files}");

return ResultWrapper<IEnumerable<string>>.Success(files);
}

public ResultWrapper<IEnumerable<BadBlock>> debug_getBadBlocks()
{
IEnumerable<BadBlock> badBlocks = _debugBridge.GetBadBlocks().Select(block => new BadBlock(block, true, _specProvider, _blockDecoder));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public interface IDebugBridge
void InsertReceipts(BlockParameter blockParameter, TxReceipt[] receipts);
SyncReportSymmary GetCurrentSyncStage();
IEnumerable<string> TraceBlockToFile(Hash256 blockHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null);
IEnumerable<string> TraceBadBlockToFile(Hash256 blockHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null);
public IEnumerable<Block> GetBadBlocks();
TxReceipt[]? GetReceiptsForBlock(BlockParameter param);
Transaction? GetTransactionFromHash(Hash256 hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ public interface IDebugRpcModule : IRpcModule
IsImplemented = true, IsSharable = false)]
ResultWrapper<IEnumerable<string>> debug_standardTraceBlockToFile(Hash256 blockHash, GethTraceOptions options = null);

[JsonRpcMethod(Description = "This method is similar to the `debug_standardTraceBlockToFile` method, but can be used to obtain information about a block that has been rejected as invalid.",
IsImplemented = true, IsSharable = false)]
ResultWrapper<IEnumerable<string>> debug_standardTraceBadBlockToFile(Hash256 blockHash, GethTraceOptions options = null);

[JsonRpcMethod(Description = "Return list of invalid blocks.")]
ResultWrapper<IEnumerable<BadBlock>> debug_getBadBlocks();
}

0 comments on commit f671118

Please sign in to comment.