예제 #1
0
        public ChainedBlock GetOrAdd(BlockHeader header)
        {
            AssertInitialized();
            var          headerHash = header.GetHash();
            ChainedBlock pindex     = GetBlock(headerHash, true);

            if (pindex != null)
            {
                return(pindex);
            }
            ChainedBlock previous = GetBlock(header.HashPrevBlock, true);

            if (previous == null)
            {
                return(null);
            }

            pindex = new ChainedBlock(header, headerHash, previous);
            if (previous.HashBlock == Tip.HashBlock)
            {
                var change = new ChainChange()
                {
                    Add              = true,
                    BlockHeader      = pindex.Header,
                    HeightOrBackstep = (uint)pindex.Height
                };
                ProcessAndRecord(change, pindex.HashBlock);
            }
            else
            {
                if (pindex.Height <= Tip.Height)
                {
                    offchainIndex.Add(pindex.HashBlock, pindex);
                }
                else
                {
                    var fork   = FindFork(pindex.EnumerateToGenesis().Select(c => c.HashBlock));
                    var change = new ChainChange()
                    {
                        Add = false,
                        HeightOrBackstep = (uint)(Tip.Height - fork.Height)
                    };
                    ProcessAndRecord(change, null);

                    foreach (var block in pindex.EnumerateToGenesis().TakeWhile(s => s != fork).Reverse())
                    {
                        change = new ChainChange()
                        {
                            Add              = true,
                            BlockHeader      = block.Header,
                            HeightOrBackstep = (uint)block.Height
                        };
                        ProcessAndRecord(change, block.HashBlock);
                    }
                }
            }
            return(pindex);
        }
예제 #2
0
        /// <summary>
        /// Force a new tip for the chain
        /// </summary>
        /// <param name="pindex"></param>
        /// <returns>forking point</returns>
        public override ChainedBlock SetTip(ChainedBlock pindex)
        {
            AssertInitialized();
            if (pindex.HashBlock == Tip.HashBlock)
            {
                return(pindex);
            }
            var fork = FindFork(pindex.EnumerateToGenesis().Select(g => g.HashBlock));

            var backStep = (uint)(Tip.Height - fork.Height);

            if (backStep != 0)
            {
                PushChange(new ChainChange()
                {
                    ChangeType       = ChainChangeType.BackStep,
                    HeightOrBackstep = backStep
                }, null);
            }
            var newBranch = pindex.EnumerateToGenesis().TakeWhile(b => b.Height != fork.Height).ToList();

            newBranch.Reverse();
            var newTip = newBranch.Count == 0 ? null : newBranch[newBranch.Count - 1];

            foreach (var block in newBranch)
            {
                var existing = GetBlock(block.HashBlock, true);
                if (existing == null || block == newTip)
                {
                    PushChange(new ChainChange()
                    {
                        ChangeType       = ChainChangeType.SetTip,
                        BlockHeader      = block.Header,
                        HeightOrBackstep = (uint)block.Height
                    }, block.HashBlock);
                }
            }
            return(fork);
        }
예제 #3
0
        private ChainedBlock SetTipNoLock(ChainedBlock block)
        {
            int height = Tip == null ? -1 : Tip.Height;

            foreach (var orphaned in EnumerateThisToFork(block))
            {
                _BlocksById.Remove(orphaned.HashBlock);
                _BlocksByHeight.Remove(orphaned.Height);
                height--;
            }
            var fork = GetBlockNoLock(height);

            foreach (var newBlock in block.EnumerateToGenesis()
                     .TakeWhile(c => c != fork))
            {
                _BlocksById.AddOrReplace(newBlock.HashBlock, newBlock);
                _BlocksByHeight.AddOrReplace(newBlock.Height, newBlock);
            }
            _Tip = block;
            return(fork);
        }
예제 #4
0
        private ChainedBlock SetTipLocked(ChainedBlock block)
        {
            int height = this.Tip == null ? -1 : this.Tip.Height;

            foreach (ChainedBlock orphaned in this.EnumerateThisToFork(block))
            {
                this.blocksById.Remove(orphaned.HashBlock);
                this.blocksByHeight.Remove(orphaned.Height);
                height--;
            }

            ChainedBlock fork = this.GetBlockLocked(height);

            foreach (ChainedBlock newBlock in block.EnumerateToGenesis().TakeWhile(c => c != fork))
            {
                this.blocksById.AddOrReplace(newBlock.HashBlock, newBlock);
                this.blocksByHeight.AddOrReplace(newBlock.Height, newBlock);
            }

            this.tip = block;
            return(fork);
        }
예제 #5
0
        public bool Validate(Network network, bool fullChain = true)
        {
            ChainedBlock tip = this.Tip;

            if (tip == null)
            {
                return(false);
            }

            if (!fullChain)
            {
                return(tip.Validate(network));
            }

            foreach (ChainedBlock block in tip.EnumerateToGenesis())
            {
                if (!block.Validate(network))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #6
0
        public PersistantChain CreateSubChain(ChainedBlock from,
                                              bool fromIncluded,
                                              ChainedBlock to,
                                              bool toIncluded,
                                              ObjectStream <ChainChange> output = null)
        {
            if (output == null)
            {
                output = new StreamObjectStream <ChainChange>();
            }

            var blocks
                =
                    to.EnumerateToGenesis()
                    .Skip(toIncluded ? 0 : 1)
                    .TakeWhile(c => c.HashBlock != from.HashBlock);

            if (fromIncluded)
            {
                blocks = blocks.Concat(new ChainedBlock[] { from });
            }

            var array = blocks.ToArray();

            Array.Reverse(array);
            foreach (var b in array)
            {
                output.WriteNext(new ChainChange()
                {
                    ChangeType       = ChainChangeType.SetTip,
                    BlockHeader      = b.Header,
                    HeightOrBackstep = (uint)b.Height
                });
            }
            return(new PersistantChain(output));
        }
예제 #7
0
		private ChainedBlock SetTipNoLock(ChainedBlock block)
		{
			int height = Tip == null ? -1 : Tip.Height;
			foreach(var orphaned in EnumerateThisToFork(block))
			{
				_BlocksById.Remove(orphaned.HashBlock);
				_BlocksByHeight.Remove(orphaned.Height);
				height--;
			}
			var fork = GetBlockNoLock(height);
			foreach(var newBlock in block.EnumerateToGenesis()
				.TakeWhile(c => c != Tip))
			{
				_BlocksById.AddOrReplace(newBlock.HashBlock, newBlock);
				_BlocksByHeight.AddOrReplace(newBlock.Height, newBlock);
			}
			_Tip = block;
			return fork;
		}
예제 #8
0
        public ChainedBlock GetOrAdd(BlockHeader header)
        {
            AssertInitialized();
            var headerHash = header.GetHash();
            ChainedBlock pindex = GetBlock(headerHash, true);
            if(pindex != null)
                return pindex;
            ChainedBlock previous = GetBlock(header.HashPrevBlock, true);
            if(previous == null)
            {
                return null;
            }

            pindex = new ChainedBlock(header, headerHash, previous);
            if(previous.HashBlock == Tip.HashBlock)
            {
                var change = new ChainChange()
                {
                    Add = true,
                    BlockHeader = pindex.Header,
                    HeightOrBackstep = (uint)pindex.Height
                };
                ProcessAndRecord(change, pindex.HashBlock);
            }
            else
            {
                if(pindex.Height <= Tip.Height)
                {
                    offchainIndex.Add(pindex.HashBlock, pindex);
                }
                else
                {
                    var fork = FindFork(pindex.EnumerateToGenesis().Select(c => c.HashBlock));
                    var change = new ChainChange()
                    {
                        Add = false,
                        HeightOrBackstep = (uint)(Tip.Height - fork.Height)
                    };
                    ProcessAndRecord(change, null);

                    foreach(var block in pindex.EnumerateToGenesis().TakeWhile(s => s != fork).Reverse())
                    {
                        change = new ChainChange()
                        {
                            Add = true,
                            BlockHeader = block.Header,
                            HeightOrBackstep = (uint)block.Height
                        };
                        ProcessAndRecord(change, block.HashBlock);
                    }
                }
            }
            return pindex;
        }
예제 #9
0
파일: Chain.cs 프로젝트: nikropht/NBitcoin
        public Chain CreateSubChain(ChainedBlock from,
            bool fromIncluded,
            ChainedBlock to,
            bool toIncluded,
            ObjectStream<ChainChange> output = null)
        {
            if(output == null)
                output = new StreamObjectStream<ChainChange>();

            var blocks
                =
                to.EnumerateToGenesis()
                .Skip(toIncluded ? 0 : 1)
                .TakeWhile(c => c.HashBlock != from.HashBlock);
            if(fromIncluded)
                blocks = blocks.Concat(new ChainedBlock[] { from });

            var array = blocks.Reverse().ToArray();
            foreach(var b in array)
            {
                output.WriteNext(new ChainChange()
                {
                    Add = true,
                    BlockHeader = b.Header,
                    HeightOrBackstep = (uint)b.Height
                });
            }
            return new Chain(output);
        }