private async void BuildHeadersSyncBatches( Context ctx, BlockTree blockTree, BlockTree syncedBlockTree, IBeaconPivot pivot, long endLowestBeaconHeader) { ctx.Feed.InitializeFeed(); long lowestHeaderNumber = pivot.PivotNumber; while (lowestHeaderNumber > endLowestBeaconHeader) { HeadersSyncBatch batch = await ctx.Feed.PrepareRequest(); batch.Should().NotBeNull(); BuildHeadersSyncBatchResponse(batch, syncedBlockTree); ctx.Feed.HandleResponse(batch); lowestHeaderNumber = lowestHeaderNumber - batch.RequestSize < endLowestBeaconHeader ? endLowestBeaconHeader : lowestHeaderNumber - batch.RequestSize; BlockHeader?lowestHeader = syncedBlockTree.FindHeader(lowestHeaderNumber, BlockTreeLookupOptions.None); blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(lowestHeader?.Hash); } }
private async void BuildAndProcessHeaderSyncBatches( Context ctx, BlockTree blockTree, BlockTree syncedBlockTree, IBeaconPivot pivot, long bestPointer, long endLowestBeaconHeader) { ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue(); blockTree.BestKnownNumber.Should().Be(bestPointer); BlockHeader?startBestHeader = syncedBlockTree.FindHeader(bestPointer, BlockTreeLookupOptions.None); blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader); blockTree.LowestInsertedBeaconHeader.Should().BeEquivalentTo(syncedBlockTree.FindHeader(pivot.PivotNumber, BlockTreeLookupOptions.None)); BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, endLowestBeaconHeader); HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); // check headers are inserted into block tree during sync blockTree.FindHeader(pivot.PivotNumber - 1, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().NotBeNull(); blockTree.LowestInsertedBeaconHeader?.Hash.Should().BeEquivalentTo(syncedBlockTree.FindHeader(endLowestBeaconHeader, BlockTreeLookupOptions.None)?.Hash); blockTree.BestKnownNumber.Should().Be(bestPointer); blockTree.BestSuggestedHeader.Should().BeEquivalentTo(startBestHeader); ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant); ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse(); }
public async Task Feed_able_to_connect_to_existing_chain_through_block_hash() { BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(600).TestObject; Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None) !; BlockTree blockTree = Build.A.BlockTree().TestObject; blockTree.SuggestBlock(genesisBlock); Block?firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None); blockTree.SuggestBlock(firstBlock); BlockHeader? pivotHeader = syncedBlockTree.FindHeader(500, BlockTreeLookupOptions.None); IBeaconPivot pivot = PreparePivot(500, new SyncConfig(), blockTree, pivotHeader); Context ctx = new (blockTree, new SyncConfig(), pivot); // fork in chain Block parent = firstBlock; for (int i = 0; i < 5; i++) { Block block = Build.A.Block.WithParent(parent).WithNonce(1).TestObject; blockTree.SuggestBlock(block); parent = block; } ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue(); blockTree.BestKnownNumber.Should().Be(6); BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 2); HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); blockTree.BestKnownNumber.Should().Be(6); ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant); ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeFalse(); }
private void PrepareHeadersResponse(HeadersSyncBatch headersSyncBatch, LatencySyncPeerMock syncPeer, IBlockTree tree) { if (headersSyncBatch != null) { long startNumber = headersSyncBatch.StartNumber; if (_maliciousByShiftedOneBack.Contains(syncPeer)) { startNumber++; TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND SHIFTED MESSAGES ({startNumber} INSTEAD OF {headersSyncBatch.StartNumber})"); } else if (_maliciousByShiftedOneForward.Contains(syncPeer)) { startNumber = Math.Max(0, startNumber - 1); TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND SHIFTED MESSAGES ({startNumber} INSTEAD OF {headersSyncBatch.StartNumber})"); } Keccak hash = tree.FindHash(startNumber); if (hash == null) { TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} CANNOT FIND {headersSyncBatch.StartNumber}"); return; } int requestSize = headersSyncBatch.RequestSize; if (_incorrectByTooLongMessages.Contains(syncPeer)) { requestSize *= 2; TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND TOO LONG MESSAGE ({requestSize} INSTEAD OF {headersSyncBatch.RequestSize})"); } else if (_incorrectByTooShortMessages.Contains(syncPeer)) { requestSize = Math.Max(1, requestSize / 2); TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND TOO SHORT MESSAGE ({requestSize} INSTEAD OF {headersSyncBatch.RequestSize})"); } BlockHeader[] headers = tree.FindHeaders(hash, requestSize, 0, false); if (_invalidBlocks.ContainsKey(syncPeer)) { for (int i = 0; i < headers.Length; i++) { if (_invalidBlocks[syncPeer].Contains(headers[i].Number)) { TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND AN INVALID BLOCK AT {headers[i].Number}"); headers[i] = Build.A.Block.WithDifficulty(1).TestObject.Header; } } } if (headers.Length > 3 && _maliciousByRepetition.Contains(syncPeer)) { headers[^ 1] = headers[^ 3];
public async Task Can_prepare_3_requests_in_a_row() { MemDbProvider memDbProvider = new MemDbProvider(); BlockTree blockTree = new BlockTree(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullTxPool.Instance, NullBloomStorage.Instance, LimboLogs.Instance); FastHeadersSyncFeed feed = new FastHeadersSyncFeed(blockTree, Substitute.For <ISyncPeerPool>(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, Substitute.For <ISyncReport>(), LimboLogs.Instance); HeadersSyncBatch batch1 = await feed.PrepareRequest(); HeadersSyncBatch batch2 = await feed.PrepareRequest(); HeadersSyncBatch batch3 = await feed.PrepareRequest(); }
private void BuildHeadersSyncBatchResponse(HeadersSyncBatch batch, IBlockTree blockTree) { batch.MarkSent(); BlockHeader?startHeader = blockTree.FindHeader(batch.StartNumber); if (startHeader == null) { return; } BlockHeader[] headers = blockTree.FindHeaders(startHeader.Hash !, batch.RequestSize, 0, true); batch.Response = headers; }