Skip to content

Commit

Permalink
Refactor TxValidator (#7386)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukasz Rozmej <[email protected]>
Co-authored-by: Jorge Mederos <[email protected]>
  • Loading branch information
3 people authored Sep 10, 2024
1 parent 6edd397 commit 030b32f
Show file tree
Hide file tree
Showing 22 changed files with 402 additions and 477 deletions.
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory
IHealthHintService? HealthHintService { get; set; }
IRpcCapabilitiesProvider? RpcCapabilitiesProvider { get; set; }
ITransactionComparerProvider? TransactionComparerProvider { get; set; }
ITxValidator? TxValidator { get; set; }
TxValidator? TxValidator { get; set; }

/// <summary>
/// Manager of block finalization
Expand Down
16 changes: 16 additions & 0 deletions src/Nethermind/Nethermind.Api/INethermindApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
// SPDX-License-Identifier: LGPL-3.0-only

#nullable enable
using System;
using Nethermind.Config;
using Nethermind.Core;
using Nethermind.Serialization.Rlp;
using Nethermind.Serialization.Rlp.TxDecoders;
using Nethermind.TxPool;

namespace Nethermind.Api
{
Expand All @@ -15,4 +20,15 @@ public T Config<T>() where T : IConfig

(IApiWithNetwork GetFromApi, INethermindApi SetInApi) ForRpc => (this, this);
}

public static class NethermindApiExtensions
{
public static void RegisterTxType(this INethermindApi api, TxType type, ITxDecoder decoder, ITxValidator validator)
{
ArgumentNullException.ThrowIfNull(api.TxValidator);

api.TxValidator.RegisterValidator(type, validator);
TxDecoder.Instance.RegisterDecoder(decoder);
}
}
}
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Api/NethermindApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public ISealEngine SealEngine
public ITxPoolInfoProvider? TxPoolInfoProvider { get; set; }
public IHealthHintService? HealthHintService { get; set; }
public IRpcCapabilitiesProvider? RpcCapabilitiesProvider { get; set; }
public ITxValidator? TxValidator { get; set; }
public TxValidator? TxValidator { get; set; }
public IBlockFinalizationManager? FinalizationManager { get; set; }
public IGasLimitCalculator? GasLimitCalculator { get; set; }

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void Zero_r_is_not_valid()
Transaction tx = Build.A.Transaction.WithSignature(signature).TestObject;

TxValidator txValidator = new(TestBlockchainIds.ChainId);
txValidator.IsWellFormed(tx, MuirGlacier.Instance).Should().BeFalse();
txValidator.IsWellFormed(tx, MuirGlacier.Instance).AsBool().Should().BeFalse();
}

private static byte CalculateV() => (byte)EthereumEcdsa.CalculateV(TestBlockchainIds.ChainId);
Expand All @@ -72,7 +72,7 @@ public void Zero_s_is_not_valid()
Transaction tx = Build.A.Transaction.WithSignature(signature).TestObject;

TxValidator txValidator = new(TestBlockchainIds.ChainId);
txValidator.IsWellFormed(tx, MuirGlacier.Instance).Should().BeFalse();
txValidator.IsWellFormed(tx, MuirGlacier.Instance).AsBool().Should().BeFalse();
}

[Test, Timeout(Timeout.MaxTestTime)]
Expand All @@ -86,7 +86,7 @@ public void Bad_chain_id_is_not_valid()
Transaction tx = Build.A.Transaction.WithSignature(signature).TestObject;

TxValidator txValidator = new(TestBlockchainIds.ChainId);
txValidator.IsWellFormed(tx, MuirGlacier.Instance).Should().BeFalse();
txValidator.IsWellFormed(tx, MuirGlacier.Instance).AsBool().Should().BeFalse();
}

[Test, Timeout(Timeout.MaxTestTime)]
Expand All @@ -100,7 +100,7 @@ public void No_chain_id_legacy_tx_is_valid()
Transaction tx = Build.A.Transaction.WithSignature(signature).TestObject;

TxValidator txValidator = new(TestBlockchainIds.ChainId);
txValidator.IsWellFormed(tx, MuirGlacier.Instance).Should().BeTrue();
txValidator.IsWellFormed(tx, MuirGlacier.Instance).AsBool().Should().BeTrue();
}

[Test, Timeout(Timeout.MaxTestTime)]
Expand All @@ -114,7 +114,7 @@ public void Is_valid_with_valid_chain_id()
Transaction tx = Build.A.Transaction.WithSignature(signature).TestObject;

TxValidator txValidator = new(TestBlockchainIds.ChainId);
txValidator.IsWellFormed(tx, MuirGlacier.Instance).Should().BeTrue();
txValidator.IsWellFormed(tx, MuirGlacier.Instance).AsBool().Should().BeTrue();
}

[Timeout(Timeout.MaxTestTime)]
Expand All @@ -134,7 +134,7 @@ public void Before_eip_155_has_to_have_valid_chain_id_unless_overridden(bool val
releaseSpec.ValidateChainId.Returns(validateChainId);

TxValidator txValidator = new(TestBlockchainIds.ChainId);
txValidator.IsWellFormed(tx, releaseSpec).Should().Be(!validateChainId);
txValidator.IsWellFormed(tx, releaseSpec).AsBool().Should().Be(!validateChainId);
}

[Timeout(Timeout.MaxTestTime)]
Expand Down Expand Up @@ -274,7 +274,7 @@ public void Transaction_with_init_code_above_max_value_is_rejected_when_eip3860E
.WithData(initCode).TestObject;

TxValidator txValidator = new(1);
txValidator.IsWellFormed(tx, releaseSpec).Should().Be(expectedResult);
txValidator.IsWellFormed(tx, releaseSpec).AsBool().Should().Be(expectedResult);
}

//leading zeros in AccessList - expected to pass (real mainnet tx)
Expand Down Expand Up @@ -345,8 +345,8 @@ public void ShardBlobTransactions_should_have_destination_set()
.WithChainId(TestBlockchainIds.ChainId)
.SignedAndResolved().TestObject;

Assert.That(txValidator.IsWellFormed(txWithoutTo, Cancun.Instance), Is.False);
Assert.That(txValidator.IsWellFormed(txWithTo, Cancun.Instance));
Assert.That(txValidator.IsWellFormed(txWithoutTo, Cancun.Instance).AsBool(), Is.False);
Assert.That(txValidator.IsWellFormed(txWithTo, Cancun.Instance).AsBool());
}

[Timeout(Timeout.MaxTestTime)]
Expand Down Expand Up @@ -404,9 +404,8 @@ public void IsWellFormed_NotBlobTxButMaxFeePerBlobGasIsSet_ReturnFalse()

Transaction tx = txBuilder.TestObject;
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

[Test]
Expand All @@ -419,9 +418,8 @@ public void IsWellFormed_NotBlobTxButBlobVersionedHashesIsSet_ReturnFalse()

Transaction tx = txBuilder.TestObject;
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

[Test]
Expand All @@ -437,9 +435,8 @@ public void IsWellFormed_BlobTxToIsNull_ReturnFalse()

Transaction tx = txBuilder.TestObject;
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}
[Test]
public void IsWellFormed_BlobTxHasMoreDataGasThanAllowed_ReturnFalse()
Expand All @@ -454,9 +451,8 @@ public void IsWellFormed_BlobTxHasMoreDataGasThanAllowed_ReturnFalse()

Transaction tx = txBuilder.TestObject;
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

[Test]
Expand All @@ -472,9 +468,8 @@ public void IsWellFormed_BlobTxHasNoBlobs_ReturnFalse()

Transaction tx = txBuilder.TestObject;
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

[Test]
Expand All @@ -490,9 +485,8 @@ public void IsWellFormed_BlobTxHasBlobOverTheSizeLimit_ReturnFalse()
Transaction tx = txBuilder.TestObject;
((ShardBlobNetworkWrapper)tx.NetworkWrapper!).Blobs[0] = new byte[Ckzg.Ckzg.BytesPerBlob + 1];
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

[Test]
Expand All @@ -508,9 +502,8 @@ public void IsWellFormed_BlobTxHasCommitmentOverTheSizeLimit_ReturnFalse()
Transaction tx = txBuilder.TestObject;
((ShardBlobNetworkWrapper)tx.NetworkWrapper!).Commitments[0] = new byte[Ckzg.Ckzg.BytesPerCommitment + 1];
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

[Test]
Expand All @@ -526,9 +519,8 @@ public void IsWellFormed_BlobTxHasProofOverTheSizeLimit_ReturnFalse()
Transaction tx = txBuilder.TestObject;
((ShardBlobNetworkWrapper)tx.NetworkWrapper!).Proofs[0] = new byte[Ckzg.Ckzg.BytesPerProof + 1];
TxValidator txValidator = new(TestBlockchainIds.ChainId);
string? error;

Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance, out error), Is.False);
Assert.That(txValidator.IsWellFormed(tx, Cancun.Instance).AsBool(), Is.False);
}

private static byte[] MakeArray(int count, params byte[] elements) =>
Expand Down
12 changes: 4 additions & 8 deletions src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ namespace Nethermind.Consensus.Validators;
public class Always : IBlockValidator, ISealValidator, IUnclesValidator, ITxValidator
{
private readonly bool _result;
private readonly ValidationResult _validationResult;

private Always(bool result)
{
_validationResult = result ? ValidationResult.Success : "Always invalid.";
_result = result;
}

Expand Down Expand Up @@ -79,16 +81,10 @@ public bool Validate(BlockHeader header, BlockHeader[] uncles)
return _result;
}

public bool IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec)
public ValidationResult IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec)
{
return _result;
return _validationResult;
}
public bool IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec, out string? errorMessage)
{
errorMessage = null;
return _result;
}

public bool ValidateWithdrawals(Block block, out string? error)
{
error = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,11 @@ private bool ValidateTransactions(Block block, IReleaseSpec spec, out string? er
{
Transaction transaction = transactions[txIndex];

if (!_txValidator.IsWellFormed(transaction, spec, out errorMessage))
ValidationResult isWellFormed = _txValidator.IsWellFormed(transaction, spec);
if (!isWellFormed)
{
if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid transaction: {errorMessage}");
if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid transaction: {isWellFormed}");
errorMessage = isWellFormed.Error;
return false;
}
}
Expand Down
Loading

0 comments on commit 030b32f

Please sign in to comment.