Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-7251: Add EL triggered consolidations #7182

Merged
merged 50 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
ca2caa9
address lukasz comments
rjnrohit May 15, 2024
a752e0e
format files
rjnrohit May 15, 2024
c36640a
fix errors
rjnrohit May 15, 2024
2e74124
modify deposit processor tests
rjnrohit May 15, 2024
bd9e8cd
flag withdrawal request processor test
rjnrohit May 15, 2024
79788d2
add requests order test
rjnrohit May 17, 2024
88e54e6
modify withdrawalRequestProcessorTest
rjnrohit May 20, 2024
6e46f06
add withdrawal modal test case
rjnrohit May 21, 2024
f633374
add withdrawal request processor test
rjnrohit May 22, 2024
a0abbc0
add handlers and classes
rjnrohit May 31, 2024
00c1be2
add api capabilities
rjnrohit May 31, 2024
c628c1a
format files
rjnrohit May 31, 2024
7d25d34
add missing handlers: EngineModuleTests.V3
rjnrohit May 31, 2024
868238c
add some tests
Jun 4, 2024
45a19be
update tests
rjnrohit Jun 5, 2024
bc0c9ff
fix tests
rjnrohit Jun 11, 2024
c6cba04
add rest of the testcases
rjnrohit Jun 11, 2024
5156339
format files
rjnrohit Jun 11, 2024
54cd0ce
fix errors
rjnrohit Jun 12, 2024
7281a31
format files
rjnrohit Jun 12, 2024
33805b7
add consolidations
rjnrohit Jun 14, 2024
de8cb10
add consolidations requests decode tests
rjnrohit Jun 14, 2024
6862a3f
format files
rjnrohit Jun 14, 2024
26b471f
add consolidationRequestProcessor
rjnrohit Jun 15, 2024
e135bac
update size in ConsolidationRequestProcessor test
rjnrohit Jun 15, 2024
37ce573
fix consolidationRequestProcessor tests
rjnrohit Jun 15, 2024
27c9d0b
rename consolidationRequest fields
rjnrohit Jun 15, 2024
4ee78c1
Merge branch 'pectra' into prague/get_payload_bodies
rjnrohit Jun 16, 2024
5d12c8d
sync with pectra
rjnrohit Jun 16, 2024
d2e5d70
Merge branch 'prague/get_payload_bodies' into feature/consolidations
rjnrohit Jun 16, 2024
6d7d743
cosmetic
MarekM25 Jun 20, 2024
e894d2b
fix specProvider issues
MarekM25 Jun 23, 2024
4ace152
consolidations wasn't processed, fixed
MarekM25 Jun 23, 2024
8ef38be
cleanups
MarekM25 Jun 23, 2024
c5017d1
Merge branch 'prague/get_payload_bodies' into feature/consolidations
MarekM25 Jun 23, 2024
da30af9
reuse WithdrawalCredentialsField
rjnrohit Jun 24, 2024
a987ce7
address PR comments
rjnrohit Jun 24, 2024
f20bee0
format files
rjnrohit Jun 24, 2024
56ca5e7
IList -> IReadOnlyList
rjnrohit Jun 24, 2024
504daba
fix engineModule error
rjnrohit Jun 24, 2024
1bb8ba0
fix merge plugin issue
rjnrohit Jun 24, 2024
50a0b3c
don't initialize list
rjnrohit Jun 24, 2024
24342fc
add continue
rjnrohit Jun 24, 2024
ffbadbb
Merge branch 'prague/get_payload_bodies' into feature/consolidations
rjnrohit Jun 24, 2024
e0efd88
format files
rjnrohit Jun 24, 2024
ef744c1
refactor handles
rjnrohit Jun 25, 2024
395b94e
Merge branch 'prague/get_payload_bodies' into feature/consolidations
rjnrohit Jun 25, 2024
16b4477
format files
rjnrohit Jun 25, 2024
e1a47d8
Merge branch 'pectra' into feature/consolidations
rjnrohit Jun 26, 2024
2df29d8
address PR comments
rjnrohit Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Nethermind/Ethereum.Blockchain.Pyspec.Test/PragueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ethereum.Test.Base;
using NUnit.Framework;
Expand All @@ -18,7 +19,7 @@ public class PragueTests : BlockchainTestBase

private static IEnumerable<BlockchainTest> LoadTests()
{
TestsSourceLoader loader = new(new LoadPyspecTestsStrategy(), $"fixtures/prague");
return (IEnumerable<BlockchainTest>)loader.LoadTests();
TestsSourceLoader loader = new(new LoadPyspecTestsStrategy(), $"fixtures/blockchain_tests/prague");
return loader.LoadTests().OfType<BlockchainTest>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Nethermind.Consensus.Messages;
using Nethermind.Consensus.Validators;
using Nethermind.Core.ConsensusRequests;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Specs;
Expand Down Expand Up @@ -202,5 +203,52 @@ public void ValidateSuggestedBlock_SuggestedBlockIsInvalid_CorrectErrorIsSet(Blo

Assert.That(error, Does.StartWith(expectedError));
}

[Test]
public void ValidateBodyAgainstHeader_BlockHasInvalidRequestRoot_ReturnsFalse()
{
Block block = Build.A.Block
.WithConsensusRequests(new ConsensusRequest[] {
Build.A.Deposit.WithIndex(0).TestObject,
Build.A.WithdrawalRequest.TestObject
})
.TestObject;
block.Header.RequestsRoot = Keccak.OfAnEmptyString;

Assert.That(
BlockValidator.ValidateBodyAgainstHeader(block.Header, block.Body),
Is.False);
}

[Test]
public void ValidateBodyRequests_BlockHasReuests_InOrder_ReturnsTrue()
{
Block block = Build.A.Block
.WithConsensusRequests(new ConsensusRequest[] {
Build.A.Deposit.WithIndex(0).TestObject,
Build.A.WithdrawalRequest.TestObject
})
.TestObject;

Assert.That(
BlockValidator.ValidateRequestsOrder(block, out string? _),
Is.True);
}

[Test]
public void ValidateBodyRequests_BlockHasReuests_OutOfOrder_ReturnsFalse()
{
Block block = Build.A.Block
.WithConsensusRequests(new ConsensusRequest[] {
Build.A.WithdrawalRequest.TestObject,
Build.A.Deposit.WithIndex(0).TestObject
})
.TestObject;

Assert.That(
BlockValidator.ValidateRequestsOrder(block, out string? _),
Is.False);
}

}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ ILogManager logManager
selectedTxs,
Array.Empty<BlockHeader>(),
spec.WithdrawalsEnabled ? Enumerable.Empty<Withdrawal>() : null,
spec.ConsensusRequestsEnabled ? Enumerable.Empty<ConsensusRequest>() : null
spec.RequestsEnabled ? Enumerable.Empty<ConsensusRequest>() : null
);
header.TxRoot = TxTrie.CalculateRoot(block.Transactions);
block.Header.Author = _sealer.Address;
Expand Down
51 changes: 35 additions & 16 deletions src/Nethermind/Nethermind.Consensus.Test/DepositProcessorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System.Linq;
using FluentAssertions;
using Nethermind.Abi;
using Nethermind.Consensus.Requests;
using Nethermind.Core;
using Nethermind.Core.ConsensusRequests;
using Nethermind.Core.Extensions;
using Nethermind.Core.Specs;
using Nethermind.Core.Test.Builders;
using NSubstitute;
using NUnit.Framework;


namespace Nethermind.Consensus.Test;

public class DepositProcessorTests
{
private AbiSignature depositEventABI = new AbiSignature("DepositEvent", AbiType.DynamicBytes, AbiType.DynamicBytes, AbiType.DynamicBytes, AbiType.DynamicBytes, AbiType.DynamicBytes);

// ToDo this test is not finished and needs to be rewritten
[Test]
public void CanParseDeposit()
public void ShouldProcessDeposit()
{
Block block = Build.A.Block.TestObject;
DepositsProcessor depositsProcessor = new();

var deposit = new Deposit()
{
Amount = 32000000000,
Expand All @@ -29,18 +35,31 @@ public void CanParseDeposit()
WithdrawalCredentials =
Bytes.FromHexString("0000000000000000000000000000000000000000000000000000000000000002")
};
var bytes = Bytes.FromHexString(
"00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080040597307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000");
AbiEncoder abiEncoder = new AbiEncoder();
var result = abiEncoder.Decode(AbiEncodingStyle.None, depositEventABI, bytes);

var newDeposit = new Deposit()
{
Pubkey = (byte[])result[0],
WithdrawalCredentials = (byte[])result[1],
Amount = ((byte[])result[2]).Reverse().ToArray().ToULongFromBigEndianByteArrayWithoutLeadingZeros(),
Signature = (byte[])result[3],
Index = ((byte[])result[4]).Reverse().ToArray().ToULongFromBigEndianByteArrayWithoutLeadingZeros(),
};
TxReceipt txReceipt = Build.A.Receipt.WithLogs(
Build.A.LogEntry.WithData(
Bytes.FromHexString(
"00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080040597307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000"
)
)
.WithAddress(
new Core.Address(Bytes.FromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"))
).TestObject
).TestObject;

IReleaseSpec spec = Substitute.For<IReleaseSpec>();

spec.DepositsEnabled.Returns(true);
spec.DepositContractAddress.Returns(
new Core.Address(Bytes.FromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"))
);

var processedDeposits = depositsProcessor.ProcessDeposits(block, new[] { txReceipt }, spec).ToList();

Assert.That(processedDeposits, Has.Count.EqualTo(1));

Deposit processedDeposit = processedDeposits[0];

processedDeposit.Should().BeEquivalentTo(deposit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Serialization.Json;

namespace Nethermind.Consensus.Messages;
public static class BlockErrorMessages
Expand Down Expand Up @@ -120,4 +121,5 @@ public static string InvalidTxInBlock(int i) =>
public static string MissingRequests => "MissingRequests: Requests cannot be null in block when EIP-6110 or EIP-7002 are activated.";
public static string RequestsNotEnabled => "RequestsNotEnabled: Requests must be null in block when EIP-6110 and EIP-7002 are not activated.";
public static string InvalidRequestsRoot(Hash256? expected, Hash256? actual) => $"InvalidRequestsRoot: Requests root hash mismatch in block: expected {expected}, got {actual}";
public static string InvalidRequestsOrder => "InvalidRequestsOrder: Requests are not in the correct order in block.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,28 @@
using Nethermind.Core.Crypto;
using Nethermind.Core.Specs;
using Nethermind.Evm.TransactionProcessing;
using Nethermind.Serialization.Rlp;
using Nethermind.State;
using Nethermind.State.Proofs;

namespace Nethermind.Consensus.Requests;

public class ConsensusRequestsProcessor(ITransactionProcessor transactionProcessor) : IConsensusRequestsProcessor
{
private readonly ConsolidationRequestsProcessor _consolidationRequestsProcessor = new(transactionProcessor);
private readonly WithdrawalRequestsProcessor _withdrawalRequestsProcessor = new(transactionProcessor);
private readonly IDepositsProcessor _depositsProcessor = new DepositsProcessor();

public void ProcessRequests(IReleaseSpec spec, IWorldState state, Block block, TxReceipt[] receipts)
{
if (!spec.DepositsEnabled && !spec.WithdrawalRequestsEnabled)
if (!spec.RequestsEnabled)
return;

using ArrayPoolList<ConsensusRequest> requestsList = new(receipts.Length * 2);

// Process deposits
requestsList.AddRange(_depositsProcessor.ProcessDeposits(block, receipts, spec));
requestsList.AddRange(_withdrawalRequestsProcessor.ReadWithdrawalRequests(spec, state, block));
requestsList.AddRange(_consolidationRequestsProcessor.ReadConsolidationRequests(spec, state, block));

ConsensusRequest[] requests = requestsList.ToArray();
Hash256 root = new RequestsTrie(requests).RootHash;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Linq;
using Nethermind.Core;
using Nethermind.Core.ConsensusRequests;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Core.Specs;
using Nethermind.Crypto;
using Nethermind.Evm;
using Nethermind.Evm.Tracing;
using Nethermind.Evm.TransactionProcessing;
using Nethermind.Int256;
using Nethermind.State;

namespace Nethermind.Consensus.Requests;

// https://eips.ethereum.org/EIPS/eip-7251#block-processing
public class ConsolidationRequestsProcessor(ITransactionProcessor transactionProcessor)
{
private const long GasLimit = 30_000_000L;

public IEnumerable<ConsolidationRequest> ReadConsolidationRequests(IReleaseSpec spec, IWorldState state, Block block)
{
if (!spec.ConsolidationRequestsEnabled)
yield break;

Address eip7251Account = spec.Eip7251ContractAddress;
if (!state.AccountExists(eip7251Account)) // not needed anymore?
yield break;

CallOutputTracer tracer = new();

Transaction? transaction = new()
{
Value = UInt256.Zero,
Data = Array.Empty<byte>(),
To = spec.Eip7251ContractAddress,
SenderAddress = Address.SystemUser,
GasLimit = GasLimit,
GasPrice = UInt256.Zero,
};
transaction.Hash = transaction.CalculateHash();

transactionProcessor.Execute(transaction, new BlockExecutionContext(block.Header), tracer);
var result = tracer.ReturnValue;
if (result == null || result.Length == 0)
yield break;

int sizeOfClass = 20 + 48 + 48;
int count = result.Length / sizeOfClass;
for (int i = 0; i < count; ++i)
{
ConsolidationRequest request = new();
Span<byte> span = new Span<byte>(result, i * sizeOfClass, sizeOfClass);
request.SourceAddress = new Address(span.Slice(0, 20).ToArray());
request.SourcePubkey = span.Slice(20, 48).ToArray();
request.TargetPubkey = span.Slice(68, 48).ToArray();

yield return request;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
using Nethermind.Core.Specs;
using System.Linq;
using Nethermind.Core.Extensions;
using System;
using Nethermind.Int256;

namespace Nethermind.Consensus.Requests;

public class DepositsProcessor : IDepositsProcessor
{
private AbiSignature depositEventABI = new("DepositEvent", AbiType.DynamicBytes, AbiType.DynamicBytes, AbiType.DynamicBytes, AbiType.DynamicBytes, AbiType.DynamicBytes);
AbiEncoder abiEncoder = new();
AbiEncoder abiEncoder = AbiEncoder.Instance;

public IEnumerable<Deposit> ProcessDeposits(Block block, TxReceipt[] receipts, IReleaseSpec spec)
{
Expand All @@ -36,9 +38,9 @@ public IEnumerable<Deposit> ProcessDeposits(Block block, TxReceipt[] receipts, I
{
Pubkey = (byte[])result[0],
WithdrawalCredentials = (byte[])result[1],
Amount = ((byte[])result[2]).Reverse().ToArray().ToULongFromBigEndianByteArrayWithoutLeadingZeros(), // ToDo not optimal - optimize
Amount = BitConverter.ToUInt64((byte[])result[2], 0),
Signature = (byte[])result[3],
Index = ((byte[])result[4]).Reverse().ToArray().ToULongFromBigEndianByteArrayWithoutLeadingZeros(), // ToDo not optimal - optimize
Index = BitConverter.ToUInt64((byte[])result[4], 0)
};

yield return newDeposit;
Expand Down

This file was deleted.

Loading