Skip to content

Commit

Permalink
Fix/check withdrawal bodiessyncfeed (#6345)
Browse files Browse the repository at this point in the history
* Also check withdrawals before insertion

* refactor

* refactor

* unit tests

* unnecessary using
  • Loading branch information
ak88 authored Dec 8, 2023
1 parent 0e0e35e commit baff631
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

using Nethermind.Consensus.Validators;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Specs;
using Nethermind.Core.Test.Builders;
using Nethermind.Logging;
using Nethermind.Specs;
using Nethermind.Specs.Test;
using NSubstitute;
using NUnit.Framework;

namespace Nethermind.Blockchain.Test.Validators
Expand All @@ -30,5 +32,61 @@ public void When_more_uncles_than_allowed_returns_false()
bool result = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithUncles(Build.A.BlockHeader.TestObject).TestObject);
Assert.False(result);
}

[Test]
public void ValidateBodyAgainstHeader_BlockIsValid_ReturnsTrue()
{
Block block = Build.A.Block
.WithTransactions(1, Substitute.For<IReleaseSpec>())
.WithWithdrawals(1)
.TestObject;

Assert.That(
BlockValidator.ValidateBodyAgainstHeader(block.Header, block.Body),
Is.True);
}

[Test]
public void ValidateBodyAgainstHeader_BlockHasInvalidTxRoot_ReturnsFalse()
{
Block block = Build.A.Block
.WithTransactions(1, Substitute.For<IReleaseSpec>())
.WithWithdrawals(1)
.TestObject;
block.Header.TxRoot = Keccak.OfAnEmptyString;

Assert.That(
BlockValidator.ValidateBodyAgainstHeader(block.Header, block.Body),
Is.False);
}


[Test]
public void ValidateBodyAgainstHeader_BlockHasInvalidUnclesRoot_ReturnsFalse()
{
Block block = Build.A.Block
.WithTransactions(1, Substitute.For<IReleaseSpec>())
.WithWithdrawals(1)
.TestObject;
block.Header.UnclesHash = Keccak.OfAnEmptyString;

Assert.That(
BlockValidator.ValidateBodyAgainstHeader(block.Header, block.Body),
Is.False);
}

[Test]
public void ValidateBodyAgainstHeader_BlockHasInvalidWithdrawalsRoot_ReturnsFalse()
{
Block block = Build.A.Block
.WithTransactions(1, Substitute.For<IReleaseSpec>())
.WithWithdrawals(1)
.TestObject;
block.Header.WithdrawalsRoot = Keccak.OfAnEmptyString;

Assert.That(
BlockValidator.ValidateBodyAgainstHeader(block.Header, block.Body),
Is.False);
}
}
}
35 changes: 27 additions & 8 deletions src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,28 +306,47 @@ private bool ValidateEip4844Fields(Block block, IReleaseSpec spec, out string? e
return true;
}

public static bool ValidateBodyAgainstHeader(BlockHeader header, BlockBody toBeValidated) =>
ValidateTxRootMatchesTxs(header, toBeValidated, out _) &&
ValidateUnclesHashMatches(header, toBeValidated, out _) &&
ValidateWithdrawalsHashMatches(header, toBeValidated, out _);

public static bool ValidateTxRootMatchesTxs(Block block, out Hash256 txRoot)
{
txRoot = new TxTrie(block.Transactions).RootHash;
return txRoot == block.Header.TxRoot;
return ValidateTxRootMatchesTxs(block.Header, block.Body, out txRoot);
}
public static bool ValidateTxRootMatchesTxs(BlockHeader header, BlockBody body, out Hash256 txRoot)
{
txRoot = new TxTrie(body.Transactions).RootHash;
return txRoot == header.TxRoot;
}

public static bool ValidateUnclesHashMatches(Block block, out Hash256 unclesHash)
{
unclesHash = UnclesHash.Calculate(block);
return ValidateUnclesHashMatches(block.Header, block.Body, out unclesHash);
}

return block.Header.UnclesHash == unclesHash;
public static bool ValidateUnclesHashMatches(BlockHeader header, BlockBody body, out Hash256 unclesHash)
{
unclesHash = UnclesHash.Calculate(body.Uncles);

return header.UnclesHash == unclesHash;
}

public static bool ValidateWithdrawalsHashMatches(Block block, out Hash256? withdrawalsRoot)
{
return ValidateWithdrawalsHashMatches(block.Header, block.Body, out withdrawalsRoot);
}

public static bool ValidateWithdrawalsHashMatches(BlockHeader header, BlockBody body, out Hash256? withdrawalsRoot)
{
withdrawalsRoot = null;
if (block.Withdrawals == null)
return block.Header.WithdrawalsRoot == null;
if (body.Withdrawals == null)
return header.WithdrawalsRoot == null;

withdrawalsRoot = new WithdrawalTrie(block.Withdrawals).RootHash;
withdrawalsRoot = new WithdrawalTrie(body.Withdrawals).RootHash;

return block.Header.WithdrawalsRoot == withdrawalsRoot;
return header.WithdrawalsRoot == withdrawalsRoot;
}

private static string Invalid(Block block) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Synchronization;
using Nethermind.Consensus.Validators;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
Expand Down Expand Up @@ -193,10 +194,7 @@ public override SyncResponseHandlingResult HandleResponse(BodiesSyncBatch? batch
private bool TryPrepareBlock(BlockInfo blockInfo, BlockBody blockBody, out Block? block)
{
BlockHeader header = _blockTree.FindHeader(blockInfo.BlockHash, blockNumber: blockInfo.BlockNumber);
Hash256 rootHash = TxTrie.CalculateRoot(blockBody.Transactions);
bool txRootIsValid = rootHash == header.TxRoot;
bool unclesHashIsValid = UnclesHash.Calculate(blockBody.Uncles) == header.UnclesHash;
if (txRootIsValid && unclesHashIsValid)
if (BlockValidator.ValidateBodyAgainstHeader(header, blockBody))
{
block = new Block(header, blockBody);
}
Expand Down

0 comments on commit baff631

Please sign in to comment.