コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        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();
            }
        }
コード例 #6
0
ファイル: Node.cs プロジェクト: jannickj/NBitcoin
        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);
        }
コード例 #7
0
 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);
 }
コード例 #8
0
ファイル: BlockStore.cs プロジェクト: glasgowdev/purple
        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();
            }
        }
コード例 #9
0
		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);
			}
		}