|
9 | 9 | using System.Threading; |
10 | 10 | using System.Threading.Tasks; |
11 | 11 | using FluentAssertions; |
| 12 | +using Nethermind.Blockchain; |
| 13 | +using Nethermind.Blockchain.Synchronization; |
12 | 14 | using Nethermind.Consensus.Producers; |
13 | 15 | using Nethermind.Core; |
14 | 16 | using Nethermind.Core.Crypto; |
15 | 17 | using Nethermind.Core.Extensions; |
16 | 18 | using Nethermind.Core.Specs; |
| 19 | +using Nethermind.Core.Test; |
17 | 20 | using Nethermind.Core.Test.Builders; |
18 | 21 | using Nethermind.Crypto; |
19 | 22 | using Nethermind.Evm; |
|
24 | 27 | using Nethermind.Merge.Plugin.Data; |
25 | 28 | using Nethermind.Merge.Plugin.GC; |
26 | 29 | using Nethermind.Merge.Plugin.Handlers; |
| 30 | +using Nethermind.Merge.Plugin.Synchronization; |
27 | 31 | using Nethermind.Serialization.Json; |
28 | 32 | using Nethermind.Serialization.Rlp; |
29 | 33 | using Nethermind.Specs.Forks; |
| 34 | +using Nethermind.Stats; |
| 35 | +using Nethermind.Synchronization.Peers; |
| 36 | +using Nethermind.Synchronization.Peers.AllocationStrategies; |
30 | 37 | using Nethermind.TxPool; |
31 | 38 | using NSubstitute; |
32 | 39 | using NUnit.Framework; |
@@ -656,6 +663,60 @@ public async Task GetBlobsV1_should_return_mix_of_blobs_and_nulls([Values(1, 2, |
656 | 663 | } |
657 | 664 | } |
658 | 665 |
|
| 666 | + [Test] |
| 667 | + public async Task Sync_proper_chain_when_header_fork_came_from_fcu_and_beacon_sync() |
| 668 | + { |
| 669 | + // fork A |
| 670 | + MergeTestBlockchain chainA = await CreateBlockchain(releaseSpec: Cancun.Instance); |
| 671 | + IEngineRpcModule rpcModuleA = CreateEngineModule(chainA, null, TimeSpan.FromDays(1)); |
| 672 | + await rpcModuleA.engine_forkchoiceUpdatedV3(new(chainA.BlockTree.Head!.Hash!, chainA.BlockTree.Head!.Hash!, chainA.BlockTree.Head!.Hash!), null); |
| 673 | + |
| 674 | + // main fork B |
| 675 | + MergeTestBlockchain chainB = await CreateBlockchain(releaseSpec: Cancun.Instance); |
| 676 | + IEngineRpcModule rpcModuleB = CreateEngineModule(chainB, null, TimeSpan.FromDays(1)); |
| 677 | + await rpcModuleB.engine_forkchoiceUpdatedV3(new(chainA.BlockTree.Head!.Hash!, chainA.BlockTree.Head!.Hash!, chainA.BlockTree.Head!.Hash!), null); |
| 678 | + |
| 679 | + // syncing chain |
| 680 | + MergeTestBlockchain chainC = await CreateBlockchain(releaseSpec: Cancun.Instance); |
| 681 | + IEngineRpcModule rpcModuleC = CreateEngineModule(chainC, null, TimeSpan.FromDays(1)); |
| 682 | + await rpcModuleC.engine_forkchoiceUpdatedV3(new(chainA.BlockTree.Head!.Hash!, chainA.BlockTree.Head!.Hash!, chainA.BlockTree.Head!.Hash!), null); |
| 683 | + |
| 684 | + ExecutionPayloadV3 payloadResultA1 = await AddNewBlockV3(rpcModuleA, chainA, 1); |
| 685 | + ExecutionPayloadV3 payloadResultA2 = await AddNewBlockV3(rpcModuleA, chainA, 1); |
| 686 | + |
| 687 | + ExecutionPayloadV3 payloadResultB1 = await AddNewBlockV3(rpcModuleB, chainB, 1); |
| 688 | + // fork |
| 689 | + ExecutionPayloadV3 payloadResultB2 = await AddNewBlockV3(rpcModuleB, chainB, 2); |
| 690 | + ExecutionPayloadV3 payloadResultB3 = await AddNewBlockV3(rpcModuleB, chainB, 1); |
| 691 | + |
| 692 | + SyncPeerMock chainAPeer = new SyncPeerMock(chainA.BlockTree); |
| 693 | + SyncPeerAllocation alloc = new SyncPeerAllocation(new PeerInfo(chainAPeer), AllocationContexts.All); |
| 694 | + alloc.AllocateBestPeer(new[] { new PeerInfo(chainAPeer) }, Substitute.For<INodeStatsManager>(), Substitute.For<IBlockTree>()); |
| 695 | + chainC.SyncPeerPool!.Allocate( |
| 696 | + Arg.Any<IPeerAllocationStrategy>(), |
| 697 | + Arg.Any<AllocationContexts>(), |
| 698 | + Arg.Any<int>(), |
| 699 | + Arg.Any<CancellationToken>())!.Returns(Task.FromResult(alloc)); |
| 700 | + |
| 701 | + |
| 702 | + await rpcModuleC.engine_forkchoiceUpdatedV3(new(payloadResultA1.BlockHash, chainC.BlockTree.GenesisHash, chainC.BlockTree.GenesisHash), null); |
| 703 | + await rpcModuleC.engine_forkchoiceUpdatedV3(new(payloadResultA2.BlockHash, chainC.BlockTree.GenesisHash, chainC.BlockTree.GenesisHash), null); |
| 704 | + await Task.Delay(1000); |
| 705 | + |
| 706 | + await rpcModuleC.engine_newPayloadV3(payloadResultB2, [], TestItem.KeccakE); |
| 707 | + await rpcModuleC.engine_newPayloadV3(payloadResultB3, [], TestItem.KeccakE); |
| 708 | + |
| 709 | + await Task.Delay(1000); |
| 710 | + AddBlockResult res = chainC.BlockTree.Insert(chainB.BlockTree.FindBlock(2)!.Header, BlockTreeInsertHeaderOptions.BeaconHeaderInsert); |
| 711 | + await rpcModuleC.engine_forkchoiceUpdatedV3(new(payloadResultB3.BlockHash, chainC.BlockTree.GenesisHash, chainC.BlockTree.GenesisHash), null); |
| 712 | + |
| 713 | + BlockHeader[]? heads = new ChainLevelHelper(chainC.BlockTree, chainC.BeaconPivot!, new SyncConfig(), chainC.LogManager) |
| 714 | + .GetNextHeaders(10, 3); |
| 715 | + |
| 716 | + Assert.That(heads?[2].Hash, Is.EqualTo(payloadResultB2.BlockHash)); |
| 717 | + Assert.That(heads?[3].Hash, Is.EqualTo(payloadResultB3.BlockHash)); |
| 718 | + } |
| 719 | + |
659 | 720 | public static IEnumerable<TestCaseData> ForkchoiceUpdatedV3DeclinedTestCaseSource |
660 | 721 | { |
661 | 722 | get |
@@ -808,7 +869,7 @@ public static IEnumerable<TestCaseData> CancunFieldsTestSource |
808 | 869 | } |
809 | 870 | } |
810 | 871 |
|
811 | | - private async Task AddNewBlockV3(IEngineRpcModule rpcModule, MergeTestBlockchain chain, int transactionCount = 0) |
| 872 | + private async Task<ExecutionPayloadV3> AddNewBlockV3(IEngineRpcModule rpcModule, MergeTestBlockchain chain, int transactionCount = 0) |
812 | 873 | { |
813 | 874 | Transaction[] txs = BuildTransactions(chain, chain.BlockTree.Head!.Hash!, TestItem.PrivateKeyA, TestItem.AddressB, (uint)transactionCount, 0, out _, out _, 0); |
814 | 875 | chain.AddTransactions(txs); |
@@ -842,6 +903,8 @@ private async Task AddNewBlockV3(IEngineRpcModule rpcModule, MergeTestBlockchain |
842 | 903 |
|
843 | 904 | ForkchoiceStateV1 newForkchoiceState = new(payload.ExecutionPayload.BlockHash, payload.ExecutionPayload.BlockHash, payload.ExecutionPayload.BlockHash); |
844 | 905 | await rpcModule.engine_forkchoiceUpdatedV3(newForkchoiceState, null); |
| 906 | + |
| 907 | + return payload.ExecutionPayload; |
845 | 908 | } |
846 | 909 |
|
847 | 910 | private async Task<(IEngineRpcModule, string?, Transaction[], MergeTestBlockchain chain)> BuildAndGetPayloadV3Result( |
|
0 commit comments