コード例 #1
0
        public HeaderNode AddToBlockIndex(BlockHeader header)
        {
            using (GlobalLocks.WriteOnMainAsync().GetAwaiter().GetResult())
            {
                // Check for duplicate
                if (TryGetKnownHeaderNode(header.Hash, out HeaderNode? headerNode))
                {
                    return(headerNode);
                }

                if (!TryGetKnownHeaderNode(header.PreviousBlockHash, out HeaderNode? previousHeader))
                {
                    ThrowHelper.ThrowNotSupportedException("Previous hash not found (shouldn't happen).");
                }

                headerNode = new HeaderNode(header, previousHeader);

                if (BestHeader == null || BestHeader.ChainWork < headerNode.ChainWork)
                {
                    BestHeader = headerNode;
                }

                HeadersTree.Add(headerNode);
                _blockHeaderRepository.TryAdd(header);

                return(headerNode);
            }
        }
コード例 #2
0
        /// <summary>
        /// Finds the ancestor of this entry in the chain that matches the given block height.
        /// </summary>
        /// <param name="height">The block height to search for.</param>
        /// <returns>The ancestor of this chain at the specified height.</returns>
        public HeaderNode?GetAncestor(int height)
        {
            if (height > Height || height < 0)
            {
                return(null);
            }

            HeaderNode current    = this;
            int        heightWalk = Height;

            while (heightWalk > height)
            {
                int heightSkip     = GetSkipHeight(heightWalk);
                int heightSkipPrev = GetSkipHeight(heightWalk - 1); //walk.Previous.Skip.Height;
                if (current.Skip != null &&
                    (heightSkip == height ||
                     (heightSkip > height && !(heightSkipPrev < (heightSkip - 2) &&
                                               heightSkipPrev >= height))))
                {
                    // Only follow Skip if pprev->pskip isn't better than pskip->pprev.
                    current    = current.Skip;
                    heightWalk = heightSkip;
                }
                else
                {
                    current = current.Previous !;
                    heightWalk--;
                }
            }

            return(current);
        }
コード例 #3
0
        public HeadersTree(ILogger <HeadersTree> logger, IConsensusParameters consensusParameters)
        {
            _logger = logger;
            _consensusParameters = consensusParameters ?? throw new ArgumentNullException(nameof(consensusParameters));

            Genesis = HeaderNode.GenerateGenesis(_consensusParameters.GenesisHeader);

            ResetToGenesis();
        }
コード例 #4
0
        public bool TryGetNext(HeaderNode headerNode, [MaybeNullWhen(false)] out HeaderNode nextHeaderNode)
        {
            using (GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult())
            {
                if (IsInBestChain(headerNode) && HeadersTree.TryGetNodeOnBestChain(headerNode.Height + 1, out nextHeaderNode))
                {
                    return(true);
                }

                nextHeaderNode = null;
                return(false);
            }
        }
コード例 #5
0
        /// <summary>
        /// Tries to get the <see cref="HeaderNode" /> giving its hash.
        /// </summary>
        /// <param name="blockHash">The block hash.</param>
        /// <param name="onlyBestChain">if set to <c>true</c> check only headers that belong to the best chain.</param>
        /// <param name="node">The header node having the passed <paramref name="blockHash"/>.</param>
        /// <returns>
        ///   <c>true</c> if the result has been found, <see langword="false" /> otherwise.
        /// </returns>
        public bool TryGetNode(UInt256?blockHash, bool onlyBestChain, [MaybeNullWhen(false)] out HeaderNode node)
        {
            if (blockHash == null)
            {
                node = null;
                return(false);
            }

            using (new ReadLock(_theLock))
            {
                return(onlyBestChain ? TryGetNodeOnBestChainNoLock(blockHash, out node !) : _knownHeaders.TryGetValue(blockHash, out node !));
            }
        }
コード例 #6
0
        /// <summary>
        /// Tries to get the <see cref="HeaderNode" /> on best chain at a specified height.
        /// </summary>
        /// <param name="height">The height.</param>
        /// <param name="node">The header node at the specified height.</param>
        /// <returns>
        ///   <c>true</c> if the result has been found, <see langword="false" /> otherwise.
        /// </returns>
        public bool TryGetNodeOnBestChain(int height, [MaybeNullWhen(false)] out HeaderNode node)
        {
            using (new ReadLock(_theLock))
            {
                if (height > _height)
                {
                    node = null !;
                    return(false);
                }

                node = GetHeaderNodeNoLock(height);
                return(true);
            }
        }
コード例 #7
0
        public ChainState(ILogger <ChainState> logger,
                          IHeadersTree headersTree,
                          ICoinsView coinsView,
                          IBlockHeaderRepository blockHeaderRepository,
                          IConsensusParameters consensusParameters)
        {
            this.logger            = logger;
            HeadersTree            = headersTree;
            this.coinsView         = coinsView;
            _blockHeaderRepository = blockHeaderRepository;
            _consensusParameters   = consensusParameters;
            ChainTip   = headersTree.Genesis;
            BestHeader = headersTree.Genesis;

            _blockHeaderRepository.TryAdd(consensusParameters.GenesisHeader);
        }
コード例 #8
0
        internal HeaderNode LastCommonAncestor(HeaderNode otherHeaderNode)
        {
            //move both chains at the height of the lower one
            HeaderNode?left  = Height > otherHeaderNode.Height ? GetAncestor(otherHeaderNode.Height) : this;
            HeaderNode?right = otherHeaderNode.Height > Height?otherHeaderNode.GetAncestor(Height) : otherHeaderNode;

            // walk back walking previous header, until we find that both are the header
            while (left != right && left != null && right != null)
            {
                left  = left.Previous;
                right = right.Previous;
            }

            //at this point returning left or right is the same, both are equals and at worst case they go back down to genesis
            return(left !);
        }
コード例 #9
0
        internal HeaderNode(BlockHeader header, HeaderNode previous)
        {
            if (header == null)
            {
                ThrowHelper.ThrowArgumentNullException(nameof(header));
            }
            if (header.Hash == null)
            {
                ThrowHelper.ThrowArgumentException($"{nameof(header)} hash cannot be null.");
            }

            Hash      = header.Hash;
            Height    = previous.Height + 1;
            Previous  = previous;
            ChainWork = previous.ChainWork + new Target(header.Bits).GetBlockProof();
            Skip      = previous.GetAncestor(GetSkipHeight(Height));
            _status   = (int)HeaderValidityStatuses.ValidTree;

            //pindexNew.TimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev.TimeMax, pindexNew.Time) : pindexNew.Time);
        }
コード例 #10
0
 public bool TryGetBlockHeader(HeaderNode headerNode, [MaybeNullWhen(false)] out BlockHeader blockHeader)
 {
     return(_blockHeaderRepository.TryGet(headerNode.Hash, out blockHeader));
 }
コード例 #11
0
 public bool IsInBestChain(HeaderNode headerNode)
 {
     return(HeadersTree.IsInBestChain(headerNode));
 }
コード例 #12
0
 public BlockLocator?GetLocator(HeaderNode headerNode)
 {
     using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult();
     return(HeadersTree.GetLocator(headerNode));
 }
コード例 #13
0
 public bool TryGetKnownHeaderNode(UInt256?blockHash, [MaybeNullWhen(false)] out HeaderNode node)
 {
     //using var readLock = new ReadLock(this.theLock);
     using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult();
     return(HeadersTree.TryGetNode(blockHash, false, out node));
 }
コード例 #14
0
 public bool TryGetBestChainHeaderNode(UInt256 blockHash, [MaybeNullWhen(false)] out HeaderNode node)
 {
     using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult();
     return(HeadersTree.TryGetNode(blockHash, true, out node));
 }
コード例 #15
0
 /// <summary>
 /// Determines whether <paramref name="expectedAncestor"/> is in same chain (can be this header itself).
 /// </summary>
 /// <param name="expectedAncestor">The expected ancestor.</param>
 /// <returns>
 ///   <c>true</c> if [is in same chain] [the specified expected ancestor]; otherwise, <c>false</c>.
 /// </returns>
 public bool IsInSameChain(HeaderNode expectedAncestor)
 {
     return(this == expectedAncestor || GetAncestor(expectedAncestor.Height)?.Hash == expectedAncestor.Hash);
 }