diff --git a/src/Nethermind/Ethereum.Test.Base/EofTest.cs b/src/Nethermind/Ethereum.Test.Base/EofTest.cs index 29d9af8b147..a773a6b9468 100644 --- a/src/Nethermind/Ethereum.Test.Base/EofTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/EofTest.cs @@ -2,8 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Ethereum.Test.Base.Interfaces; -using System.Collections.Generic; -using System.Numerics; +using Nethermind.Evm.EvmObjectFormat; namespace Ethereum.Test.Base; public class Result @@ -16,6 +15,7 @@ public class Result public class VectorTest { public byte[] Code { get; set; } + public ValidationStrategy ContainerKind { get; set; } } public class EofTest : IEthereumTest diff --git a/src/Nethermind/Ethereum.Test.Base/EofTestBase.cs b/src/Nethermind/Ethereum.Test.Base/EofTestBase.cs index fe2333d7c27..0a718285bcb 100644 --- a/src/Nethermind/Ethereum.Test.Base/EofTestBase.cs +++ b/src/Nethermind/Ethereum.Test.Base/EofTestBase.cs @@ -53,6 +53,7 @@ protected bool RunTest(EofTest test, ITxTracer txTracer) var vector = test.Vector; var code = vector.Code; + var strategy = vector.ContainerKind; var fork = test.Result.Fork switch { "Prague" => Nethermind.Specs.Forks.Prague.Instance, @@ -68,7 +69,7 @@ protected bool RunTest(EofTest test, ITxTracer txTracer) _ => throw new NotSupportedException($"Fork {test.Result.Fork} is not supported") }; - bool result = CodeDepositHandler.IsValidWithEofRules(fork, code, 1); + bool result = CodeDepositHandler.IsValidWithEofRules(fork, code, 1, strategy); return result; } } diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index f1d3e6dd24c..4f150159d35 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -12,6 +12,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm.EvmObjectFormat; using Nethermind.Int256; using Nethermind.Serialization.Json; using Nethermind.Serialization.Rlp; @@ -309,6 +310,11 @@ public static IEnumerable ConvertToEofTests(string json) VectorTestJson vectorJson = pair.Value; VectorTest vector = new(); vector.Code = Bytes.FromHexString(vectorJson.Code); + vector.ContainerKind = + ("INITCODE".Equals(vectorJson.ContainerKind) + ? ValidationStrategy.ValidateInitcodeMode + : ValidationStrategy.ValidateRuntimeMode) + | ValidationStrategy.ValidateFullBody; foreach (var result in vectorJson.Results) { diff --git a/src/Nethermind/Ethereum.Test.Base/VectorTestJson.cs b/src/Nethermind/Ethereum.Test.Base/VectorTestJson.cs index db2d6398892..5466b7eb379 100644 --- a/src/Nethermind/Ethereum.Test.Base/VectorTestJson.cs +++ b/src/Nethermind/Ethereum.Test.Base/VectorTestJson.cs @@ -8,5 +8,6 @@ namespace Ethereum.Test.Base; public class VectorTestJson { public string Code { get; set; } + public string ContainerKind { get; set; } public Dictionary Results { get; set; } } diff --git a/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs b/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs index fa7428e1c9d..e2efd6b8422 100644 --- a/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs +++ b/src/Nethermind/Nethermind.Evm/EvmObjectFormat/Handlers/EofV1.cs @@ -440,11 +440,7 @@ private bool ValidateContainer(EofContainer eofContainer, ValidationStrategy val if (validationStrategy.HasFlag(ValidationStrategy.Validate)) { - // Clear the Initcode flag for subcontainer - ValidationStrategy subContainerValidation = validationStrategy & ~ValidationStrategy.ValidateInitcodeMode; - // Set the Runtime flag for subcontainer - subContainerValidation |= ValidationStrategy.ValidateRuntimeMode; - containers.Enqueue((new EofContainer(subsection, header.Value), subContainerValidation)); + containers.Enqueue((new EofContainer(subsection, header.Value), worklet.Strategy)); } } else @@ -637,6 +633,7 @@ private bool ValidateInstructions(EofContainer eofContainer, int sectionId, Vali ReadOnlySpan currentTypeSection = eofContainer.TypeSections[sectionId].Span; var isCurrentSectionNonReturning = currentTypeSection[OUTPUTS_OFFSET] == 0x80; + bool hasRequiredSectionExit = isCurrentSectionNonReturning; int position; Instruction opcode = Instruction.STOP; @@ -710,7 +707,7 @@ private bool ValidateInstructions(EofContainer eofContainer, int sectionId, Vali return false; } - containersWorklist.Enqueue(runtimeContainerId + 1, ValidationStrategy.ValidateRuntimeMode); + containersWorklist.Enqueue(runtimeContainerId + 1, ValidationStrategy.ValidateRuntimeMode | ValidationStrategy.ValidateFullBody); BitmapHelper.HandleNumbits(EofValidator.ONE_BYTE_LENGTH, invalidJumpDestinations, ref nextPosition); } @@ -736,6 +733,7 @@ private bool ValidateInstructions(EofContainer eofContainer, int sectionId, Vali } else if (opcode is Instruction.JUMPF) { + hasRequiredSectionExit = true; if (nextPosition + EofValidator.TWO_BYTE_LENGTH > code.Length) { if (Logger.IsTrace) Logger.Trace($"EOF: Eof{VERSION}, {Instruction.JUMPF} Argument underflow"); @@ -762,6 +760,12 @@ private bool ValidateInstructions(EofContainer eofContainer, int sectionId, Vali return false; } + if (isCurrentSectionNonReturning && !isTargetSectionNonReturning) + { + if (Logger.IsTrace) Logger.Trace($"EOF: Eof{VERSION}, {Instruction.JUMPF} from non-returning must target non-returning"); + return false; + } + sectionsWorklist.Enqueue(targetSectionId, strategy); BitmapHelper.HandleNumbits(EofValidator.TWO_BYTE_LENGTH, invalidJumpDestinations, ref nextPosition); } @@ -839,10 +843,15 @@ private bool ValidateInstructions(EofContainer eofContainer, int sectionId, Vali sectionsWorklist.Enqueue(targetSectionId, strategy); BitmapHelper.HandleNumbits(EofValidator.TWO_BYTE_LENGTH, invalidJumpDestinations, ref nextPosition); } - else if (opcode is Instruction.RETF && isCurrentSectionNonReturning) + else if (opcode is Instruction.RETF) { - if (Logger.IsTrace) Logger.Trace($"EOF: Eof{VERSION}, non returning sections are not allowed to use opcode {Instruction.RETF}"); - return false; + hasRequiredSectionExit = true; + if (isCurrentSectionNonReturning) + { + if (Logger.IsTrace) + Logger.Trace($"EOF: Eof{VERSION}, non returning sections are not allowed to use opcode {Instruction.RETF}"); + return false; + } } else if (opcode is Instruction.DATALOADN) { @@ -913,6 +922,12 @@ private bool ValidateInstructions(EofContainer eofContainer, int sectionId, Vali return false; } + if (!hasRequiredSectionExit) + { + if (Logger.IsTrace) Logger.Trace($"EOF: Eof{VERSION}, Code section {sectionId} is returning and does not have a RETF or JUMPF"); + return false; + } + var result = BitmapHelper.CheckCollision(invalidJumpDestinations, jumpDestinations); if (result) {