diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs
index 5638afebb00..445b63a1fa7 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayload.cs
@@ -18,7 +18,7 @@ namespace Nethermind.Merge.Plugin.Data;
///
/// Represents an object mapping the ExecutionPayload structure of the beacon chain spec.
///
-public class ExecutionPayload : IForkValidator
+public class ExecutionPayload : IForkValidator, IExecutionPayloadParams
{
public ExecutionPayload() { } // Needed for tests
@@ -165,14 +165,16 @@ public void SetTransactions(params Transaction[] transactions)
public override string ToString() => $"{BlockNumber} ({BlockHash.ToShortString()})";
- public virtual bool ValidateParams(IReleaseSpec spec, int version, [NotNullWhen(false)] out string? error)
+ ExecutionPayload IExecutionPayloadParams.ExecutionPayload => this;
+
+ public virtual ValidationResult ValidateParams(IReleaseSpec spec, int version, out string? error)
{
int GetVersion() => Withdrawals is null ? 1 : 2;
if (spec.IsEip4844Enabled)
{
error = "ExecutionPayloadV3 expected";
- return false;
+ return ValidationResult.Fail;
}
int actualVersion = GetVersion();
@@ -184,12 +186,9 @@ public virtual bool ValidateParams(IReleaseSpec spec, int version, [NotNullWhen(
_ => actualVersion > version ? $"ExecutionPayloadV{version} expected" : null
};
- return error is null;
+ return error is null ? ValidationResult.Success : ValidationResult.Fail;
}
public virtual bool ValidateFork(ISpecProvider specProvider) =>
!specProvider.GetSpec(BlockNumber, Timestamp).IsEip4844Enabled;
-
- public bool ValidateParams(ISpecProvider specProvider, int version, [NotNullWhen(false)] out string? error) =>
- ValidateParams(specProvider.GetSpec(BlockNumber, Timestamp), version, out error);
}
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs
index 1c6dbc4b1dc..94f7170cd02 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/ExecutionPayloadV3.cs
@@ -47,13 +47,6 @@ public override bool TryGetBlock(out Block? block, UInt256? totalDifficulty = nu
return true;
}
- public override bool ValidateParams(IReleaseSpec spec, int version, [NotNullWhen(false)] out string? error)
- {
- // handled by `JsonObject` attribute of the class
- error = null;
- return true;
- }
-
public override bool ValidateFork(ISpecProvider specProvider) =>
specProvider.GetSpec(BlockNumber, Timestamp).IsEip4844Enabled;
}
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs
new file mode 100644
index 00000000000..51723767251
--- /dev/null
+++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/IExecutionPayloadParams.cs
@@ -0,0 +1,49 @@
+// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
+// SPDX-License-Identifier: LGPL-3.0-only
+
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Nethermind.Core.Extensions;
+using Nethermind.Core.Specs;
+
+namespace Nethermind.Merge.Plugin.Data;
+
+public interface IExecutionPayloadParams
+{
+ ExecutionPayload ExecutionPayload { get; }
+ ValidationResult ValidateParams(IReleaseSpec spec, int version, out string? error);
+}
+
+public enum ValidationResult : byte { Success, Fail, Invalid };
+
+public class ExecutionPayloadV3Params : IExecutionPayloadParams
+{
+ private readonly ExecutionPayloadV3 _executionPayload;
+ private readonly byte[]?[] _blobVersionedHashes;
+
+ public ExecutionPayloadV3Params(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes)
+ {
+ _executionPayload = executionPayload;
+ _blobVersionedHashes = blobVersionedHashes;
+ }
+
+ public ExecutionPayload ExecutionPayload => _executionPayload;
+
+ public ValidationResult ValidateParams(IReleaseSpec spec, int version, out string? error)
+ {
+ static IEnumerable FlattenHashesFromTransactions(ExecutionPayloadV3 payload) =>
+ payload.GetTransactions()
+ .Where(t => t.BlobVersionedHashes is not null)
+ .SelectMany(t => t.BlobVersionedHashes!);
+
+ if (FlattenHashesFromTransactions(_executionPayload).SequenceEqual(_blobVersionedHashes, Bytes.NullableEqualityComparer))
+ {
+ error = null;
+ return ValidationResult.Success;
+ }
+
+ error = "Blob versioned hashes do not match";
+ return ValidationResult.Invalid;
+ }
+}
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs b/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs
index c92f8b9475d..8a27a65fb10 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/Data/PayloadStatusV1.cs
@@ -17,10 +17,11 @@ public class PayloadStatusV1
public static readonly PayloadStatusV1 Accepted = new() { Status = PayloadStatus.Accepted };
- public static PayloadStatusV1 Invalid(Keccak? latestValidHash) => new()
+ public static PayloadStatusV1 Invalid(Keccak? latestValidHash, string? validationError = null) => new()
{
Status = PayloadStatus.Invalid,
- LatestValidHash = latestValidHash
+ LatestValidHash = latestValidHash,
+ ValidationError = validationError
};
///
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs
index 470d191e67d..41aa57d7b61 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Cancun.cs
@@ -17,44 +17,7 @@ public partial class EngineRpcModule : IEngineRpcModule
private readonly IAsyncHandler _getPayloadHandlerV3;
public Task> engine_newPayloadV3(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes) =>
- ValidateFork(executionPayload) ?? PreValidatePayload(executionPayload, blobVersionedHashes) ?? NewPayload(executionPayload, 3);
-
- private ResultWrapper? PreValidatePayload(ExecutionPayloadV3 executionPayload, byte[]?[] blobVersionedHashes)
- {
- ResultWrapper ErrorResult(string error)
- {
- if (_logger.IsWarn) _logger.Warn(error);
- return ResultWrapper.Success(
- new PayloadStatusV1
- {
- Status = PayloadStatus.Invalid,
- LatestValidHash = null,
- ValidationError = error
- });
- }
-
- static IEnumerable FlattenHashesFromTransactions(ExecutionPayloadV3 payload) =>
- payload.GetTransactions()
- .Where(t => t.BlobVersionedHashes is not null)
- .SelectMany(t => t.BlobVersionedHashes!);
-
- return !FlattenHashesFromTransactions(executionPayload).SequenceEqual(blobVersionedHashes, Bytes.NullableEqualityComparer)
- ? ErrorResult("Blob versioned hashes do not match")
- : null;
- }
-
- private ResultWrapper? ValidateFork(ExecutionPayload executionPayload)
- {
- if (executionPayload.ValidateFork(_specProvider))
- {
- return null;
- }
- else
- {
- if (_logger.IsWarn) _logger.Warn($"The payload is not supported by the current fork");
- return ResultWrapper.Fail("unsupported fork", ErrorCodes.UnsupportedFork);
- }
- }
+ NewPayload(new ExecutionPayloadV3Params(executionPayload, blobVersionedHashes), 3);
public async Task> engine_getPayloadV3(byte[] payloadId) =>
await _getPayloadHandlerV3.HandleAsync(payloadId);
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs
index 8a09b6399ce..585af416360 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs
@@ -6,6 +6,7 @@
using System.Threading;
using System.Threading.Tasks;
using Nethermind.Consensus.Producers;
+using Nethermind.Core.Specs;
using Nethermind.JsonRpc;
using Nethermind.Merge.Plugin.Data;
using Nethermind.Merge.Plugin.GC;
@@ -64,12 +65,24 @@ private async Task> ForkchoiceUpdated(F
}
}
- private async Task> NewPayload(ExecutionPayload executionPayload, int version)
+ private async Task> NewPayload(IExecutionPayloadParams executionPayloadParams, int version)
{
- if (!executionPayload.ValidateParams(_specProvider, version, out string? error))
+ ExecutionPayload executionPayload = executionPayloadParams.ExecutionPayload;
+
+ if (!executionPayload.ValidateFork(_specProvider))
+ {
+ if (_logger.IsWarn) _logger.Warn($"The payload is not supported by the current fork");
+ return ResultWrapper.Fail("unsupported fork", version < 2 ? ErrorCodes.InvalidParams : ErrorCodes.UnsupportedFork);
+ }
+
+ IReleaseSpec releaseSpec = _specProvider.GetSpec(executionPayload.BlockNumber, executionPayload.Timestamp);
+ ValidationResult validationResult = executionPayloadParams.ValidateParams(releaseSpec, version, out string? error);
+ if (validationResult != ValidationResult.Success)
{
if (_logger.IsWarn) _logger.Warn(error);
- return ResultWrapper.Fail(error, ErrorCodes.InvalidParams);
+ return validationResult == ValidationResult.Fail
+ ? ResultWrapper.Fail(error!, ErrorCodes.InvalidParams)
+ : ResultWrapper.Success(PayloadStatusV1.Invalid(null, error));
}
if (await _locker.WaitAsync(_timeout))
diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs
index ec1e72e540b..99792015ae3 100644
--- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs
+++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Shanghai.cs
@@ -30,5 +30,5 @@ public Task> engine_forkchoiceUpdatedV2
=> _executionGetPayloadBodiesByRangeV1Handler.Handle(start, count);
public Task> engine_newPayloadV2(ExecutionPayload executionPayload)
- => ValidateFork(executionPayload) ?? NewPayload(executionPayload, 2);
+ => NewPayload(executionPayload, 2);
}