Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Nethermind/Ethereum.Test.Base/BlockchainTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ protected async Task<EthereumTestResult> RunTest(BlockchainTest test, Stopwatch?
IBlockValidator blockValidator = container.Resolve<IBlockValidator>();
blockchainProcessor.Start();

BlockHeader parentHeader;
// Genesis processing
using (stateProvider.BeginScope(null))
{
Expand All @@ -167,6 +168,7 @@ protected async Task<EthereumTestResult> RunTest(BlockchainTest test, Stopwatch?

blockTree.SuggestBlock(genesisBlock);
genesisProcessed.WaitOne();
parentHeader = genesisBlock.Header;
}

List<(Block Block, string ExpectedException)> correctRlp = DecodeRlps(test, failOnInvalidRlp);
Expand All @@ -181,7 +183,7 @@ protected async Task<EthereumTestResult> RunTest(BlockchainTest test, Stopwatch?
{
// TODO: mimic the actual behaviour where block goes through validating sync manager?
correctRlp[i].Block.Header.IsPostMerge = correctRlp[i].Block.Difficulty == 0;
if (!test.SealEngineUsed || blockValidator.ValidateSuggestedBlock(correctRlp[i].Block, out var _error))
if (!test.SealEngineUsed || blockValidator.ValidateSuggestedBlock(correctRlp[i].Block, parentHeader, out var _error))
{
blockTree.SuggestBlock(correctRlp[i].Block);
}
Expand All @@ -204,6 +206,8 @@ protected async Task<EthereumTestResult> RunTest(BlockchainTest test, Stopwatch?
{
Assert.Fail($"Unexpected exception during processing: {e}");
}

parentHeader = correctRlp[i].Block.Header;
}

await blockchainProcessor.StopAsync(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class BlockValidatorTests
public void Setup()
{
IHeaderValidator headerValidator = Substitute.For<IHeaderValidator>();
headerValidator.Validate(Arg.Any<BlockHeader>()).Returns(true);
headerValidator.Validate(Arg.Any<BlockHeader>(), Arg.Any<BlockHeader>()).Returns(true);
_blockValidator = new(
Substitute.For<ITxValidator>(),
headerValidator,
Expand All @@ -38,8 +38,9 @@ public void Setup()
[Test]
public void Accepts_valid_block()
{
Block block = Build.A.Block.WithEncodedSize(Eip7934Constants.DefaultMaxRlpBlockSize).TestObject;
bool result = _blockValidator.ValidateSuggestedBlock(block);
BlockHeader header = Build.A.BlockHeader.TestObject;
Block block = Build.A.Block.WithParent(header).WithEncodedSize(Eip7934Constants.DefaultMaxRlpBlockSize).TestObject;
bool result = _blockValidator.ValidateSuggestedBlock(block, header, out _);
Assert.That(result, Is.True);
}

Expand All @@ -54,10 +55,11 @@ public void When_more_uncles_than_allowed_returns_false()
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, releaseSpec));

BlockValidator blockValidator = new(txValidator, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance);
bool noiseRemoved = blockValidator.ValidateSuggestedBlock(Build.A.Block.TestObject);
BlockHeader parent = Build.A.BlockHeader.TestObject;
bool noiseRemoved = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithParent(parent).TestObject, parent, out _);
Assert.That(noiseRemoved, Is.True);

bool result = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithUncles(Build.A.BlockHeader.TestObject).TestObject);
bool result = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithParent(parent).WithUncles(Build.A.BlockHeader.TestObject).TestObject, parent, out _);
Assert.That(result, Is.False);
}

Expand Down Expand Up @@ -184,18 +186,23 @@ public void ValidateProcessedBlock_StateRootIsWrong_ErrorIsSet()

private static IEnumerable<TestCaseData> BadSuggestedBlocks()
{
BlockHeader parent = Build.A.BlockHeader.TestObject;

yield return new TestCaseData(
Build.A.Block.WithHeader(Build.A.BlockHeader.WithUnclesHash(Keccak.Zero).TestObject).TestObject,
Build.A.Block.WithHeader(Build.A.BlockHeader.WithParent(parent).WithUnclesHash(Keccak.Zero).TestObject).TestObject,
parent,
Substitute.For<ISpecProvider>(),
"InvalidUnclesHash");

yield return new TestCaseData(
Build.A.Block.WithHeader(Build.A.BlockHeader.WithTransactionsRoot(Keccak.Zero).TestObject).TestObject,
Build.A.Block.WithHeader(Build.A.BlockHeader.WithParent(parent).WithTransactionsRoot(Keccak.Zero).TestObject).TestObject,
parent,
Substitute.For<ISpecProvider>(),
"InvalidTxRoot");

yield return new TestCaseData(
Build.A.Block.WithBlobGasUsed(131072)
.WithParent(parent)
.WithExcessBlobGas(1)
.WithTransactions(
Build.A.Transaction.WithShardBlobTxTypeAndFields(1)
Expand All @@ -204,22 +211,24 @@ private static IEnumerable<TestCaseData> BadSuggestedBlocks()
.Signed()
.TestObject)
.TestObject,
parent,
new CustomSpecProvider(((ForkActivation)0, Cancun.Instance)),
"InsufficientMaxFeePerBlobGas");

yield return new TestCaseData(
Build.A.Block.WithEncodedSize(Eip7934Constants.DefaultMaxRlpBlockSize + 1).TestObject,
Build.A.Block.WithParent(parent).WithEncodedSize(Eip7934Constants.DefaultMaxRlpBlockSize + 1).TestObject,
parent,
new CustomSpecProvider(((ForkActivation)0, Osaka.Instance)),
"ExceededBlockSizeLimit");
}

[TestCaseSource(nameof(BadSuggestedBlocks))]
public void ValidateSuggestedBlock_SuggestedBlockIsInvalid_CorrectErrorIsSet(Block suggestedBlock, ISpecProvider specProvider, string expectedError)
public void ValidateSuggestedBlock_SuggestedBlockIsInvalid_CorrectErrorIsSet(Block suggestedBlock, BlockHeader? parent, ISpecProvider specProvider, string expectedError)
{
TxValidator txValidator = new(TestBlockchainIds.ChainId);
BlockValidator sut = new(txValidator, Always.Valid, Always.Valid, specProvider, LimboLogs.Instance);

sut.ValidateSuggestedBlock(suggestedBlock, out string? error);
sut.ValidateSuggestedBlock(suggestedBlock, parent, out string? error);

Assert.That(error, Does.StartWith(expectedError));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void Setup()
public void Valid_when_valid()
{
_block.Header.SealEngineType = SealEngineType.None;
bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
if (!result)
{
foreach (string error in _testLogger.LogList)
Expand All @@ -78,7 +78,7 @@ public void When_gas_limit_too_high()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -89,7 +89,7 @@ public void When_gas_limit_just_correct_high()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.True);
}

Expand All @@ -100,7 +100,7 @@ public void When_gas_limit_just_correct_low()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.True);
}

Expand All @@ -111,7 +111,7 @@ public void When_gas_limit_is_just_too_low()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -122,7 +122,7 @@ public void When_gas_used_above_gas_limit()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -134,7 +134,7 @@ public void When_no_parent_invalid()
_block.Header.Hash = _block.CalculateHash();
_block.Header.MaybeParent = null;

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -145,7 +145,7 @@ public void When_timestamp_same_as_parent()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -156,7 +156,7 @@ public void When_extra_data_too_long()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -167,7 +167,7 @@ public void When_incorrect_difficulty_then_invalid()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -178,7 +178,7 @@ public void When_incorrect_number_then_invalid()
_block.Header.SealEngineType = SealEngineType.None;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand Down Expand Up @@ -251,7 +251,7 @@ public void When_block_number_is_negative()
_block.Header.Number = -1;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -261,7 +261,7 @@ public void When_gas_used_is_negative()
_block.Header.GasUsed = -1;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -274,7 +274,7 @@ public void When_total_difficulty_null_we_should_skip_total_difficulty_validatio
_block.Header.Hash = _block.CalculateHash();

HeaderValidator validator = new HeaderValidator(_blockTree, Always.Valid, _specProvider, new OneLoggerLogManager(new(_testLogger)));
bool result = validator.Validate(_block.Header);
bool result = validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.True);
}

Expand Down Expand Up @@ -306,7 +306,7 @@ public void When_total_difficulty_zero_we_should_skip_total_difficulty_validatio
_specProvider.UpdateMergeTransitionInfo(null, (UInt256?)ttd);

HeaderValidator validator = new(_blockTree, Always.Valid, _specProvider, new OneLoggerLogManager(new(_testLogger)));
bool result = validator.Validate(_block.Header);
bool result = validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.EqualTo(expectedResult));
}

Expand All @@ -316,7 +316,7 @@ public void When_gas_limit_is_negative()
_block.Header.GasLimit = -1;
_block.Header.Hash = _block.CalculateHash();

bool result = _validator.Validate(_block.Header);
bool result = _validator.Validate(_block.Header, _parentBlock.Header);
Assert.That(result, Is.False);
}

Expand All @@ -326,7 +326,7 @@ public void Validate_HashIsWrong_ErrorMessageIsSet()
HeaderValidator sut = new HeaderValidator(_blockTree, Always.Valid, Substitute.For<ISpecProvider>(), new OneLoggerLogManager(new(_testLogger)));
_block.Header.Hash = Keccak.Zero;
string? error;
sut.Validate(_block.Header, false, out error);
sut.Validate(_block.Header, _parentBlock.Header, false, out error);

Assert.That(error, Does.StartWith("InvalidHeaderHash"));
}
Expand All @@ -335,9 +335,8 @@ public void Validate_HashIsWrong_ErrorMessageIsSet()
public void When_given_parent_is_wrong()
{
_block.Header.Hash = _block.CalculateHash();
_block.Header.MaybeParent = new WeakReference<BlockHeader>(Build.A.BlockHeader.WithNonce(999).TestObject);

bool result = _validator.Validate(_block.Header, false, out string? error);
bool result = _validator.Validate(_block.Header, Build.A.BlockHeader.WithNonce(999).TestObject, false, out string? error);

Assert.That(result, Is.False);
Assert.That(error, Does.StartWith("Mismatched parent"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,27 @@ public static bool Blob_gas_fields_should_be_set(IReleaseSpec spec, ulong? blobG
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec));
HeaderValidator headerValidator = new(Substitute.For<IBlockTree>(), Always.Valid, specProvider, TestLogManager.Instance);
BlockValidator blockValidator = new(Always.Valid, headerValidator, Always.Valid, specProvider, TestLogManager.Instance);
BlockHeader parent = Build.A.BlockHeader.TestObject;
return blockValidator.ValidateSuggestedBlock(Build.A.Block
.WithBlobGasUsed(blobGasUsed)
.WithExcessBlobGas(excessBlobGas)
.WithWithdrawalsRoot(TestItem.KeccakA)
.WithWithdrawals(TestItem.WithdrawalA_1Eth)
.WithParent(Build.A.BlockHeader.TestObject)
.TestObject);
.WithParent(parent)
.TestObject,
parent,
out _);
}

[TestCaseSource(nameof(BlobsPerBlockCountTestCases))]
public bool Blobs_per_block_count_is_valid(IReleaseSpec spec, ulong blobGasUsed)
{
ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, spec));
BlockValidator blockValidator = new(Always.Valid, Always.Valid, Always.Valid, specProvider, TestLogManager.Instance);
BlockHeader parent = Build.A.BlockHeader.TestObject;
return blockValidator.ValidateSuggestedBlock(
Build.A.Block
.WithParent(parent)
.WithWithdrawalsRoot(TestItem.KeccakA)
.WithWithdrawals(TestItem.WithdrawalA_1Eth)
.WithBlobGasUsed(blobGasUsed)
Expand All @@ -48,7 +53,9 @@ public bool Blobs_per_block_count_is_valid(IReleaseSpec spec, ulong blobGasUsed)
.WithType(TxType.Blob)
.WithMaxFeePerBlobGas(ulong.MaxValue)
.WithBlobVersionedHashes(1).TestObject).ToArray())
.TestObject);
.TestObject,
parent,
out _);
}

private static IEnumerable<TestCaseData> BlobsPerBlockCountTestCases()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,19 @@ public TestBlockValidator(Queue<bool> suggestedValidationResults, Queue<bool> pr
_processedValidationResults = processedValidationResults ?? throw new ArgumentNullException(nameof(processedValidationResults));
}

public bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle)
{
return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue();
}

public bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle, [NotNullWhen(false)] out string? error)
{
var result = _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue();
error = result ? null : "";
return result;
}

public bool Validate(BlockHeader header, bool isUncle)
{
return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue();
}
public bool Validate(BlockHeader header, bool isUncle, [NotNullWhen(false)] out string? error)
public bool ValidateSuggestedBlock(Block block, BlockHeader? parent, [NotNullWhen(false)] out string? error, bool validateHashes = true)
{
error = null;
return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue();
}

public bool ValidateSuggestedBlock(Block block)
{
return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue();
}
public bool ValidateSuggestedBlock(Block block, [NotNullWhen(false)] out string? error, bool validateHashes = true)
{
error = null;
return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue();
}
public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, Block suggestedBlock)
{
return _alwaysSameResultForProcessed ?? _processedValidationResults.Dequeue();
}
public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, Block suggestedBlock, [NotNullWhen(false)] out string? error)
{
error = null;
Expand Down
Loading