public void OnNodeConnected(BitcoinEndpoint endpoint) { BlockLocator locator = null; lock (lockObject) { endpoints.Add(endpoint, new EndpointState(endpoint)); if (requiredBlocks.Any()) { int minRequiredBlockHeight = requiredBlocks.Values.Min(b => b.Height); int locatorHeight = minRequiredBlockHeight - 1; List<StoredBlock> parentBlocks = node.Blockchain.GetBlocksByHeight(BlockLocator.GetRequiredBlockHeights(locatorHeight)); locator = new BlockLocator(); foreach (StoredBlock block in parentBlocks) { locator.AddHash(block.Height, block.Hash); } } } if (locator != null) { endpoint.WriteMessage(new GetBlocksMessage(endpoint.ProtocolVersion, locator.GetHashes(), new byte[32])); } }
private void ProcessHeadersMessage(BitcoinEndpoint endpoint, HeadersMessage message) { List<StoredBlock> storedBlocks = node.Blockchain.AddHeaders(message.Headers); //todo: save blockLocator per node between requests? BlockLocator blockLocator = new BlockLocator(); //todo: what should happen if message contains headers from different branchas? bool hasSavedHeaders = false; foreach (StoredBlock block in storedBlocks) { if (block.Height >= 0) { //todo: this code assumes that blocks in storedBlocks collections are in order of ascending height and belong to one branch blockLocator.AddHash(block.Height, block.Hash); hasSavedHeaders = true; } } //todo: review this condition if (hasSavedHeaders) { RequestHeaders(endpoint, blockLocator); } }
public void TestTruncation() { BlockLocator locator = new BlockLocator(); for (int i = 1; i <= 20; i++) { locator.AddHash(i, BitConverter.GetBytes(i)); } Assert.That(locator.GetHashes().Select(val => BitConverter.ToInt32(val, 0)), Is.EqualTo(new int[] { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 8, 4 })); locator.AddHash(16, BitConverter.GetBytes(10016)); Assert.That(locator.GetHashes().Select(val => BitConverter.ToInt32(val, 0)), Is.EqualTo(new int[] { 10016, 15, 14, 13, 12, 11, 8, 4 })); }
private static void RequestHeaders(BitcoinEndpoint endpoint, BlockLocator blockLocator) { endpoint.WriteMessage(new GetHeadersMessage(endpoint.ProtocolVersion, blockLocator.GetHashes(), new byte[32])); }
private void TestSet(int from, int to) { BlockLocator locator = new BlockLocator(); for (int i = from; i <= to; i++) { locator.AddHash(i, BitConverter.GetBytes(i)); } Assert.That( locator.GetHashes().Select(val => BitConverter.ToInt32(val, 0)).ToList(), Is.EqualTo(CalculateExpectedHeights(from, to)), $"Testing set from {from} to {to}."); }