Example #1
0
        /// <summary>
        /// Set the tip if header is higher than current tip and previous blocks are present
        /// </summary>
        /// <param name="header"></param>
        /// <param name="chainedBlock">null if header could not be chained with previous blocks</param>
        /// <returns>True if header is the new Tip</returns>
        public bool TrySetTip(BlockHeader header, out ChainedBlock chainedBlock)
        {
            AssertInitialized();
            var headerHash = header.GetHash();

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

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

            chainedBlock = new ChainedBlock(header, headerHash, previous);
            if (chainedBlock.Height > Tip.Height)
            {
                SetTip(chainedBlock);
            }
            else
            {
                var change = new ChainChange()
                {
                    ChangeType       = ChainChangeType.AddBlock,
                    HeightOrBackstep = (uint)chainedBlock.Height,
                    BlockHeader      = chainedBlock.Header
                };
                PushChange(change, chainedBlock.HashBlock);
            }
            return(true);
        }
Example #2
0
 private void Process(ChainChange change, uint256 blockHash)
 {
     if (blockHash == null && change.BlockHeader != null)
     {
         blockHash = change.BlockHeader.GetHash();
     }
     if (change.Add)
     {
         var previous = GetBlock(change.BlockHeader.HashPrevBlock, false);
         if (Initialized && previous == null && change.HeightOrBackstep != StartHeight)
         {
             throw new InvalidOperationException("Previous block missing");
         }
         var block = Initialized ? new ChainedBlock(change.BlockHeader, blockHash, previous) : new ChainedBlock(change.BlockHeader, (int)change.HeightOrBackstep);
         index.AddOrReplace(blockHash, block);
         vChain.Add(block);
     }
     else
     {
         foreach (var removed in vChain.Resize(vChain.Count - (int)change.HeightOrBackstep).Where(r => r != null))
         {
             offchainIndex.AddOrReplace(removed.HashBlock, removed);
             index.Remove(removed.HashBlock);
         }
     }
 }
Example #3
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);
        }
Example #4
0
        public void Initialize(BlockHeader header, int height)
        {
            if (Initialized)
            {
                throw new InvalidOperationException("Already initialized");
            }
            var change = new ChainChange()
            {
                ChangeType       = ChainChangeType.SetTip,
                BlockHeader      = header,
                HeightOrBackstep = (uint)height
            };

            PushChange(change, header.GetHash());
        }
Example #5
0
        public void Initialize(BlockHeader header, int height)
        {
            if (Initialized)
            {
                throw new InvalidOperationException("Already initialized");
            }
            var change = new ChainChange()
            {
                Add              = true,
                BlockHeader      = header,
                HeightOrBackstep = (uint)height
            };

            ProcessAndRecord(change, header.GetHash());
        }
Example #6
0
 void Process(ChainChange change, uint256 blockHash)
 {
     if (blockHash == null && change.BlockHeader != null)
     {
         blockHash = change.BlockHeader.GetHash();
     }
     if (change.ChangeType == ChainChangeType.SetTip || change.ChangeType == ChainChangeType.AddBlock)
     {
         var previous = GetBlock(change.BlockHeader.HashPrevBlock, true);
         if (Initialized && previous == null && change.HeightOrBackstep != StartHeight)
         {
             throw new InvalidOperationException("Previous block missing");
         }
         var block = Initialized ? new ChainedBlock(change.BlockHeader, blockHash, previous) : new ChainedBlock(change.BlockHeader, (int)change.HeightOrBackstep);
         if (change.ChangeType == ChainChangeType.SetTip)
         {
             List <ChainedBlock> newMain       = new List <ChainedBlock>();
             ChainedBlock        previousBlock = block;
             while (previousBlock != null && previousBlock.Height >= Height + 1)
             {
                 newMain.Add(previousBlock);
                 previousBlock = previousBlock.Previous;
             }
             newMain.Reverse();
             foreach (var newBlock in newMain)
             {
                 vChain.Add(newBlock);
                 index.AddOrReplace(newBlock.HashBlock, newBlock);
                 offchainIndex.Remove(newBlock.HashBlock);
             }
         }
         else
         {
             offchainIndex.AddOrReplace(blockHash, block);
         }
     }
     else if (change.ChangeType == ChainChangeType.BackStep)
     {
         foreach (var removed in vChain.Resize(vChain.Count - (int)change.HeightOrBackstep).Where(r => r != null))
         {
             offchainIndex.AddOrReplace(removed.HashBlock, removed);
             index.Remove(removed.HashBlock);
         }
     }
 }
Example #7
0
 public void PushChange(ChainChange change, uint256 blockHash)
 {
     Process(change, blockHash);
     _Changes.WriteNext(change);
     _NextToProcess++;
 }
Example #8
0
 private void ProcessAndRecord(ChainChange change, uint256 blockHash)
 {
     Process(change, blockHash);
     _Changes.WriteNext(change);
     _NextToProcess++;
 }
Example #9
0
 private void ProcessAndRecord(ChainChange change, uint256 blockHash)
 {
     Process(change, blockHash);
     _Changes.WriteNext(change);
     _NextToProcess++;
 }
Example #10
0
 private void Process(ChainChange change, uint256 blockHash)
 {
     if(blockHash == null && change.BlockHeader != null)
         blockHash = change.BlockHeader.GetHash();
     if(change.Add)
     {
         var previous = GetBlock(change.BlockHeader.HashPrevBlock, false);
         if(Initialized && previous == null && change.HeightOrBackstep != StartHeight)
             throw new InvalidOperationException("Previous block missing");
         var block = Initialized ? new ChainedBlock(change.BlockHeader, blockHash, previous) : new ChainedBlock(change.BlockHeader, (int)change.HeightOrBackstep);
         index.AddOrReplace(blockHash, block);
         vChain.Add(block);
     }
     else
     {
         foreach(var removed in vChain.Resize(vChain.Count - (int)change.HeightOrBackstep).Where(r => r != null))
         {
             offchainIndex.AddOrReplace(removed.HashBlock, removed);
             index.Remove(removed.HashBlock);
         }
     }
 }
Example #11
0
 public void Initialize(BlockHeader header, int height)
 {
     if(Initialized)
         throw new InvalidOperationException("Already initialized");
     var change = new ChainChange()
     {
         Add = true,
         BlockHeader = header,
         HeightOrBackstep = (uint)height
     };
     ProcessAndRecord(change, header.GetHash());
 }
Example #12
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;
        }