/// <summary> /// Synchronize a given Chain to the tip of the given node if its height is higher. (Thread safe). /// </summary> /// <param name="peer">Node to synchronize the chain for.</param> /// <param name="chain">The chain to synchronize.</param> /// <param name="hashStop">The location until which it synchronize.</param> /// <param name="cancellationToken"></param> /// <returns></returns> private IEnumerable <ChainedHeader> SynchronizeChain(INetworkPeer peer, ChainBase chain, uint256 hashStop = null, CancellationToken cancellationToken = default(CancellationToken)) { ChainedHeader oldTip = chain.Tip; List <ChainedHeader> headers = this.GetHeadersFromFork(peer, oldTip, hashStop, cancellationToken).ToList(); if (headers.Count == 0) { return(new ChainedHeader[0]); } ChainedHeader newTip = headers[headers.Count - 1]; if (newTip.Height <= oldTip.Height) { throw new ProtocolException("No tip should have been recieved older than the local one"); } foreach (ChainedHeader header in headers) { if (!header.Validate(peer.Network)) { throw new ProtocolException("A header which does not pass proof of work verification has been received"); } } chain.SetTip(newTip); return(headers); }
public static async Task UpdateChain(this IAsyncEnumerable <ChainBlockHeader> entries, ChainBase chain, CancellationToken cancellation = default(CancellationToken)) { var enumerator = await entries.GetAsyncEnumeratorAsync(cancellation).ConfigureAwait(false); Stack <ChainBlockHeader> toApply = new Stack <ChainBlockHeader>(); while (await enumerator.MoveNextAsync(cancellation).ConfigureAwait(false)) { var entry = enumerator.Current; var prev = chain.GetBlock(entry.Header.HashPrevBlock); if (prev == null) { toApply.Push(entry); } else { toApply.Push(entry); break; } } while (toApply.Count > 0) { var newTip = toApply.Pop(); var chained = new ChainedBlock(newTip.Header, newTip.BlockId, chain.GetBlock(newTip.Header.HashPrevBlock)); chain.SetTip(chained); } }
public void SynchronizeChain(ChainBase chain) { Dictionary <uint256, BlockHeader> headers = new Dictionary <uint256, BlockHeader>(); HashSet <uint256> inChain = new HashSet <uint256>(); inChain.Add(chain.GetBlock(0).HashBlock); foreach (var header in Enumerate(true).Select(b => b.Item.Header)) { var hash = header.GetHash(); headers.Add(hash, header); } List <uint256> toRemove = new List <uint256>(); while (headers.Count != 0) { foreach (var header in headers) { if (inChain.Contains(header.Value.HashPrevBlock)) { toRemove.Add(header.Key); chain.SetTip(header.Value); inChain.Add(header.Key); } } foreach (var item in toRemove) { headers.Remove(item); } if (toRemove.Count == 0) { break; } toRemove.Clear(); } }
public static void UpdateChain(this IEnumerable <ChainBlockHeader> entries, ChainBase chain) { Stack <ChainBlockHeader> toApply = new Stack <ChainBlockHeader>(); foreach (var entry in entries) { var prev = chain.GetBlock(entry.Header.HashPrevBlock); if (prev == null) { toApply.Push(entry); } else { toApply.Push(entry); break; } } while (toApply.Count > 0) { var newTip = toApply.Pop(); var chained = new ChainedBlock(newTip.Header, newTip.BlockId, chain.GetBlock(newTip.Header.HashPrevBlock)); chain.SetTip(chained); } }
public void SynchronizeChain(ChainBase chain) { Dictionary <uint256, Block> blocks = new Dictionary <uint256, Block>(); Dictionary <uint256, ChainedBlock> chainedBlocks = new Dictionary <uint256, ChainedBlock>(); HashSet <uint256> inChain = new HashSet <uint256>(); inChain.Add(chain.GetBlock(0).HashBlock); chainedBlocks.Add(chain.GetBlock(0).HashBlock, chain.GetBlock(0)); foreach (var block in this.Enumerate(false).Select(b => b.Item)) { var hash = block.GetHash(); blocks.Add(hash, block); } List <uint256> toRemove = new List <uint256>(); while (blocks.Count != 0) { // to optimize keep a track of the last block ChainedBlock last = chain.GetBlock(0); foreach (var block in blocks) { if (inChain.Contains(block.Value.Header.HashPrevBlock)) { toRemove.Add(block.Key); ChainedBlock chainedBlock; if (last.HashBlock == block.Value.Header.HashPrevBlock) { chainedBlock = last; } else { if (!chainedBlocks.TryGetValue(block.Value.Header.HashPrevBlock, out chainedBlock)) { break; } } var chainedHeader = new ChainedBlock(block.Value.Header, block.Value.GetHash(), chainedBlock); chain.SetTip(chainedHeader); chainedBlocks.TryAdd(chainedHeader.HashBlock, chainedHeader); inChain.Add(block.Key); last = chainedHeader; } } foreach (var item in toRemove) { blocks.Remove(item); } if (toRemove.Count == 0) { break; } toRemove.Clear(); } }
public IEnumerable <ChainedBlock> SynchronizeChain(ChainBase chain, uint256 hashStop = null, CancellationToken cancellationToken = default(CancellationToken)) { List <ChainedBlock> headers = new List <ChainedBlock>(); foreach (var header in GetHeadersFromFork(chain.Tip, hashStop, cancellationToken)) { chain.SetTip(header); headers.Add(header); } return(headers); }
public void SynchronizeChain(ChainBase chain) { if (chain.Tip != null && chain.Genesis.HashBlock != Configuration.Network.GetGenesis().GetHash()) { throw new ArgumentException("Incompatible Network between the indexer and the chain", "chain"); } if (chain.Tip == null) { chain.SetTip(new ChainedBlock(Configuration.Network.GetGenesis().Header, 0)); } GetChainChangesUntilFork(chain.Tip, false) .UpdateChain(chain); }
public void SynchronizeChain(ChainBase chain) { var headers = new Dictionary <uint256, BlockHeader>(); var inChain = new HashSet <uint256>(); inChain.Add(chain.GetBlock(0).HashBlock); foreach (BlockHeader header in Enumerate(true).Select(b => b.Item.Header)) { uint256 hash = header.GetHash(this.Network.NetworkOptions); headers.Add(hash, header); } var toRemove = new List <uint256>(); while (headers.Any()) { foreach (KeyValuePair <uint256, BlockHeader> header in headers) { if (inChain.Contains(header.Value.HashPrevBlock)) { toRemove.Add(header.Key); chain.SetTip(header.Value); inChain.Add(header.Key); } } foreach (uint256 item in toRemove) { headers.Remove(item); } if (!toRemove.Any()) { break; } toRemove.Clear(); } }
public static void UpdateChain(this IEnumerable<ChainBlockHeader> entries, ChainBase chain) { Stack<ChainBlockHeader> toApply = new Stack<ChainBlockHeader>(); foreach(var entry in entries) { var prev = chain.GetBlock(entry.Header.HashPrevBlock); if(prev == null) toApply.Push(entry); else { toApply.Push(entry); break; } } while(toApply.Count > 0) { var newTip = toApply.Pop(); var chained = new ChainedBlock(newTip.Header, newTip.BlockId, chain.GetBlock(newTip.Header.HashPrevBlock)); chain.SetTip(chained); } }