diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 4906a41f0d3..df6401fb10a 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -176,5 +176,27 @@ public bool Before_eip_1559_has_to_be_legacy_or_access_list_tx(TxType txType, bo IReleaseSpec releaseSpec = new ReleaseSpec() {IsEip2930Enabled = eip2930, IsEip1559Enabled = eip1559}; return txValidator.IsWellFormed(tx, releaseSpec); } + + + [TestCase(TxType.Legacy, ExpectedResult = true)] + [TestCase(TxType.AccessList, ExpectedResult = false)] + [TestCase(TxType.EIP1559, ExpectedResult = false)] + public bool Chain_Id_required_for_non_legacy_transactions_after_Berlin(TxType txType) + { + byte[] sigData = new byte[65]; + sigData[31] = 1; // correct r + sigData[63] = 1; // correct s + sigData[64] = 38; + Signature signature = new Signature(sigData); + Transaction tx = Build.A.Transaction + .WithType(txType > TxType.AccessList ? TxType.Legacy : txType) + .WithAccessList(txType == TxType.AccessList ? new AccessList(new Dictionary>()) : null) + .WithSignature(signature).TestObject; + + tx.Type = txType; + + TxValidator txValidator = new TxValidator(ChainId.Mainnet); + return txValidator.IsWellFormed(tx, Berlin.Instance); + } } } diff --git a/src/Nethermind/Nethermind.Blockchain/Validators/TxValidator.cs b/src/Nethermind/Nethermind.Blockchain/Validators/TxValidator.cs index 07da1282fc7..a5ed01066f9 100644 --- a/src/Nethermind/Nethermind.Blockchain/Validators/TxValidator.cs +++ b/src/Nethermind/Nethermind.Blockchain/Validators/TxValidator.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Nethermind. If not, see . +using System; using System.Numerics; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -49,16 +50,39 @@ public bool IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec) transaction.GasLimit >= IntrinsicGasCalculator.Calculate(transaction, releaseSpec) && /* if it is a call or a transfer then we require the 'To' field to have a value while for an init it will be empty */ - ValidateSignature(transaction.Signature, releaseSpec); + ValidateSignature(transaction.Signature, releaseSpec) && + ValidateChainId(transaction); } private bool ValidateTxType(Transaction transaction, IReleaseSpec releaseSpec) { - return transaction.Type == TxType.Legacy || - (transaction.Type == TxType.AccessList && releaseSpec.UseTxAccessLists) || - (transaction.Type == TxType.EIP1559 && releaseSpec.IsEip1559Enabled); + switch (transaction.Type) + { + case TxType.Legacy: + return true; + case TxType.AccessList: + return releaseSpec.UseTxAccessLists; + case TxType.EIP1559: + return releaseSpec.IsEip1559Enabled; + default: + return false; + } } - + + private bool ValidateChainId(Transaction transaction) + { + switch (transaction.Type) + { + case TxType.Legacy: + return true; + case TxType.AccessList: + case TxType.EIP1559: + return transaction.ChainId == _chainIdValue; + default: + return false; + } + } + private bool ValidateSignature(Signature signature, IReleaseSpec spec) { BigInteger sValue = signature.SAsSpan.ToUnsignedBigInteger();