diff --git a/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs b/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs index ffd084d7eb3..666792bffb3 100644 --- a/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs +++ b/src/Nethermind/Nethermind.Optimism.Test/RlpDecoderTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using Nethermind.Core; +using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; using Nethermind.Serialization.Rlp; using NUnit.Framework; @@ -11,19 +12,26 @@ namespace Nethermind.Optimism.Test; public class RlpDecoderTests { + private TxDecoder _decoder = null!; + + [SetUp] + public void Setup() + { + _decoder = TxDecoder.Instance; + _decoder.RegisterDecoder(new OptimismTxDecoder()); + _decoder.RegisterDecoder(new OptimismLegacyTxDecoder()); + } + [Test] public void Can_decode_non_null_Transaction() { - TxDecoder decoder = TxDecoder.Instance; - decoder.RegisterDecoder(new OptimismTxDecoder()); - Transaction tx = Build.A.Transaction.WithType(TxType.DepositTx).TestObject; - RlpStream rlpStream = new(decoder.GetLength(tx, RlpBehaviors.None)); - decoder.Encode(rlpStream, tx); + RlpStream rlpStream = new(_decoder.GetLength(tx, RlpBehaviors.None)); + _decoder.Encode(rlpStream, tx); rlpStream.Reset(); - Transaction? decodedTx = decoder.Decode(rlpStream); + Transaction? decodedTx = _decoder.Decode(rlpStream); decodedTx.Should().NotBeNull(); } @@ -31,17 +39,32 @@ public void Can_decode_non_null_Transaction() [Test] public void Can_decode_non_null_Transaction_through_Rlp() { - TxDecoder decoder = TxDecoder.Instance; - decoder.RegisterDecoder(new OptimismTxDecoder()); + _decoder.RegisterDecoder(new OptimismTxDecoder()); Transaction tx = Build.A.Transaction.WithType(TxType.DepositTx).TestObject; - RlpStream rlpStream = new(decoder.GetLength(tx, RlpBehaviors.None)); - decoder.Encode(rlpStream, tx); + RlpStream rlpStream = new(_decoder.GetLength(tx, RlpBehaviors.None)); + _decoder.Encode(rlpStream, tx); rlpStream.Reset(); Transaction? decodedTx = Rlp.Decode(rlpStream); decodedTx.Should().NotBeNull(); } + + [Test] + public void Can_decode_Legacy_Empty_Signature() + { + _decoder.RegisterDecoder(new OptimismTxDecoder()); + + // See: https://github.com/NethermindEth/nethermind/issues/7880 + var hexBytes = + "f901c9830571188083030d4094420000000000000000000000000000000000000780b901a4cbd4ece9000000000000000000000000420000000000000000000000000000000000001000000000000000000000000099c9fc46f92e8a1c0dec1b1747d010903e884be10000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000005711800000000000000000000000000000000000000000000000000000000000000e4662a633a000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58000000000000000000000000117274dde02bc94006185af87d78beab28ceae06000000000000000000000000117274dde02bc94006185af87d78beab28ceae06000000000000000000000000000000000000000000000000000000000c3d8b8000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808080"; + var bytes = Bytes.FromHexString(hexBytes); + var context = bytes.AsRlpValueContext(); + + var transaction = _decoder.Decode(ref context); + + transaction.Should().NotBeNull(); + } } diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index 1036e22ba9e..d3003a98dc5 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -38,7 +38,7 @@ protected override async Task InitBlockchain() await base.InitBlockchain(); api.RegisterTxType(new OptimismTxDecoder(), Always.Valid); - api.RegisterTxType(new OptimismLegacyTxDecoder(), new OptimismLegacyTxValidator()); + api.RegisterTxType(new OptimismLegacyTxDecoder(), new OptimismLegacyTxValidator(api.SpecProvider!.ChainId)); } protected override ITransactionProcessor CreateTransactionProcessor(CodeInfoRepository codeInfoRepository, VirtualMachine virtualMachine) diff --git a/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs b/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs index eb85cd9e22e..605656f384c 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismLegacyTxDecoder.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using Nethermind.Consensus.Validators; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -11,7 +12,7 @@ namespace Nethermind.Optimism; -public class OptimismLegacyTxDecoder : LegacyTxDecoder +public sealed class OptimismLegacyTxDecoder : LegacyTxDecoder { protected override Signature? DecodeSignature(ulong v, ReadOnlySpan rBytes, ReadOnlySpan sBytes, Signature? fallbackSignature = null, RlpBehaviors rlpBehaviors = RlpBehaviors.None) @@ -24,16 +25,26 @@ public class OptimismLegacyTxDecoder : LegacyTxDecoder } } -public class OptimismLegacyTxValidator : ITxValidator +public sealed class OptimismLegacyTxValidator(ulong chainId) : ITxValidator { + private ITxValidator _postBedrockValidator = new CompositeTxValidator([ + IntrinsicGasTxValidator.Instance, + new LegacySignatureTxValidator(chainId), + ContractSizeTxValidator.Instance, + NonBlobFieldsTxValidator.Instance, + NonSetCodeFieldsTxValidator.Instance + ]); + public ValidationResult IsWellFormed(Transaction transaction, IReleaseSpec releaseSpec) { - // In op bedrock eip1559 activated with bedrock - if (releaseSpec.IsEip1559Enabled) + // In Optimism, EIP1559 is activated in Bedrock + var isPreBedrock = !releaseSpec.IsEip1559Enabled; + if (isPreBedrock) { - return transaction.Signature is null ? new ValidationResult("Empty signature") : ValidationResult.Success; + // Pre-Bedrock we peform no validation at all + return ValidationResult.Success; } - return ValidationResult.Success; + return _postBedrockValidator.IsWellFormed(transaction, releaseSpec); } } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index a294cbe1c01..91956235e67 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -86,7 +86,7 @@ public void InitTxTypesAndRlpDecoders(INethermindApi api) if (ShouldRunSteps(api)) { api.RegisterTxType(new OptimismTxDecoder(), Always.Valid); - api.RegisterTxType(new OptimismLegacyTxDecoder(), new OptimismLegacyTxValidator()); + api.RegisterTxType(new OptimismLegacyTxDecoder(), new OptimismLegacyTxValidator(api.SpecProvider!.ChainId)); Rlp.RegisterDecoders(typeof(OptimismReceiptMessageDecoder).Assembly, true); } }