public void ConnectHeaders_NewAndExistingHeaders_ShouldCreateNewHeaders() { var testContext = new TestContext(); ChainedHeaderTree chainedHeaderTree = testContext.CreateChainedHeaderTree(); ChainedHeader chainTip = testContext.ExtendAChain(10); chainedHeaderTree.Initialize(chainTip, true); // initialize the tree with 10 headers chainTip.BlockDataAvailability = BlockDataAvailabilityState.BlockAvailable; ChainedHeader newChainTip = testContext.ExtendAChain(10, chainTip); // create 10 more headers List <BlockHeader> listOfExistingHeaders = testContext.ChainedHeaderToList(chainTip, 10); List <BlockHeader> listOfNewHeaders = testContext.ChainedHeaderToList(newChainTip, 10); chainTip.BlockValidationState = ValidationState.FullyValidated; ConnectNewHeadersResult connectedHeadersResultOld = chainedHeaderTree.ConnectNewHeaders(2, listOfExistingHeaders); ConnectNewHeadersResult connectedHeadersResultNew = chainedHeaderTree.ConnectNewHeaders(1, listOfNewHeaders); Assert.Equal(21, chainedHeaderTree.GetChainedHeadersByHash().Count); Assert.Equal(10, listOfNewHeaders.Count); Assert.True(testContext.NoDownloadRequested(connectedHeadersResultOld)); Assert.Equal(listOfNewHeaders.Last(), connectedHeadersResultNew.DownloadTo.Header); Assert.Equal(listOfNewHeaders.First(), connectedHeadersResultNew.DownloadFrom.Header); }
public void ConnectHeaders_HeadersFromTwoPeers_ShouldCreateTwoPeerTips() { var testContext = new TestContext(); ChainedHeaderTree chainedHeaderTree = testContext.CreateChainedHeaderTree(); ChainedHeader chainTip = testContext.ExtendAChain(10); chainedHeaderTree.Initialize(chainTip, true); List <BlockHeader> listOfExistingHeaders = testContext.ChainedHeaderToList(chainTip, 4); ConnectNewHeadersResult connectNewHeaders1 = chainedHeaderTree.ConnectNewHeaders(1, listOfExistingHeaders); ConnectNewHeadersResult connectNewHeaders2 = chainedHeaderTree.ConnectNewHeaders(2, listOfExistingHeaders); Assert.Single(chainedHeaderTree.GetPeerIdsByTipHash()); Assert.Equal(11, chainedHeaderTree.GetChainedHeadersByHash().Count); Assert.Equal(3, chainedHeaderTree.GetPeerIdsByTipHash().First().Value.Count); Assert.Equal(ChainedHeaderTree.LocalPeerId, chainedHeaderTree.GetPeerIdsByTipHash().First().Value.ElementAt(0)); Assert.Equal(1, chainedHeaderTree.GetPeerIdsByTipHash().First().Value.ElementAt(1)); Assert.Equal(2, chainedHeaderTree.GetPeerIdsByTipHash().First().Value.ElementAt(2)); Assert.True(testContext.NoDownloadRequested(connectNewHeaders1)); Assert.True(testContext.NoDownloadRequested(connectNewHeaders2)); }
public void ChainHasTwoCheckPoints_ChainCoveringOnlyFirstCheckPointIsPresented_ChainIsDiscardedUpUntilFirstCheckpoint() { // Chain header tree setup. // Initial chain has 2 headers. // Example: h1=h2. const int initialChainSize = 2; const int currentChainExtension = 6; TestContext ctx = new TestContextBuilder().WithInitialChain(initialChainSize).UseCheckpoints().Build(); ChainedHeaderTree cht = ctx.ChainedHeaderTree; ChainedHeader initialChainTip = ctx.InitialChainTip; ChainedHeader extendedChainTip = ctx.ExtendAChain(currentChainExtension, initialChainTip); // i.e. h1=h2=h3=h4=h5=h6=h7=h8 List <BlockHeader> listOfCurrentChainHeaders = ctx.ChainedHeaderToList(extendedChainTip, initialChainSize + currentChainExtension); // Setup two known checkpoints at header 4 and 7. // Example: h1=h2=h3=(h4)=h5=h6=(h7)=h8. const int firstCheckpointHeight = 4; const int secondCheckpointHeight = 7; var checkpoint1 = new CheckpointFixture(firstCheckpointHeight, listOfCurrentChainHeaders[firstCheckpointHeight - 1]); var checkpoint2 = new CheckpointFixture(secondCheckpointHeight, listOfCurrentChainHeaders[secondCheckpointHeight - 1]); ctx.SetupCheckpoints(checkpoint1, checkpoint2); // Setup new chain that only covers first checkpoint but doesn't cover second checkpoint. // Example: h1=h2=h3=(h4)=h5=h6=x7=x8=x9=x10. const int newChainExtension = 4; extendedChainTip = extendedChainTip.GetAncestor(6); // walk back to block 6 extendedChainTip = ctx.ExtendAChain(newChainExtension, extendedChainTip); List <BlockHeader> listOfNewChainHeaders = ctx.ChainedHeaderToList(extendedChainTip, extendedChainTip.Height); // First 5 blocks are presented by peer 1. // DownloadTo should be set to a checkpoint 1. ConnectNewHeadersResult result = cht.ConnectNewHeaders(1, listOfNewChainHeaders.Take(5).ToList()); result.DownloadTo.HashBlock.Should().Be(checkpoint1.Header.GetHash()); // Remaining 5 blocks are presented by peer 1 which do not cover checkpoint 2. // InvalidHeaderException should be thrown. List <BlockHeader> violatingHeaders = listOfNewChainHeaders.Skip(5).ToList(); Action connectAction = () => { cht.ConnectNewHeaders(1, violatingHeaders); }; connectAction.Should().Throw <CheckpointMismatchException>(); // Make sure headers for violating chain don't exist. foreach (BlockHeader header in violatingHeaders) { Assert.False(cht.GetChainedHeadersByHash().ContainsKey(header.GetHash())); } }
public void ConnectHeaders_NoNewHeadersToConnect_ShouldReturnNothingToDownload() { TestContext testContext = new TestContextBuilder().WithInitialChain(10).Build(); ChainedHeaderTree chainedHeaderTree = testContext.ChainedHeaderTree; ChainedHeader chainTip = testContext.InitialChainTip; List <BlockHeader> listOfExistingHeaders = testContext.ChainedHeaderToList(chainTip, 4); ConnectNewHeadersResult connectNewHeadersResult = chainedHeaderTree.ConnectNewHeaders(1, listOfExistingHeaders); Assert.True(testContext.NoDownloadRequested(connectNewHeadersResult)); Assert.Equal(11, chainedHeaderTree.GetChainedHeadersByHash().Count); }
public void ConnectHeaders_NoNewHeadersToConnect_ShouldReturnNothingToDownload() { var testContext = new TestContext(); ChainedHeaderTree chainedHeaderTree = testContext.CreateChainedHeaderTree(); ChainedHeader chainTip = testContext.ExtendAChain(10); chainedHeaderTree.Initialize(chainTip, true); List <BlockHeader> listOfExistingHeaders = testContext.ChainedHeaderToList(chainTip, 4); ConnectNewHeadersResult connectNewHeadersResult = chainedHeaderTree.ConnectNewHeaders(1, listOfExistingHeaders); Assert.True(testContext.NoDownloadRequested(connectNewHeadersResult)); Assert.Equal(11, chainedHeaderTree.GetChainedHeadersByHash().Count); }
public static ChainedHeader GetPeerTipChainedHeaderByPeerId(this ChainedHeaderTree chainedHeaderTree, int peer) { return(chainedHeaderTree.GetChainedHeadersByHash()[chainedHeaderTree.GetPeerTipsByPeerId()[peer]]); }