예제 #1
0
        void Intercept(IncomingMessage message, Action act)
        {
            var inv = message.Message.Payload as InvPayload;

            if (inv != null)
            {
                if (inv.Inventory.Any(i => ((i.Type & InventoryType.MSG_BLOCK) != 0) && !Chain.Contains(i.Hash)))
                {
                    _Refresh.Dispose();                     //No need of periodical refresh, the peer is notifying us
                    if (AutoSync)
                    {
                        TrySync();
                    }
                }
            }

            // == GetHeadersPayload ==
            // represents our height from the peer's point of view
            // it is sent from the peer on first connect, in response to  Inv(Block)
            // or in response to HeaderPayload until an empty array is returned
            // this payload notifies peers of our current best validated height
            // use the ChainState.HighestValidatedPoW property (not Chain.Tip)
            // if the peer is behind/equal to our best height an empty array is sent back

            // Ignoring getheaders from peers because node is in initial block download
            var getheaders = message.Message.Payload as GetHeadersPayload;

            if (getheaders != null && CanRespondToGetHeaders &&
                (!this.SharedState.IsInitialBlockDownload ||
                 this.AttachedNode.Behavior <ConnectionManagerBehavior>().Whitelisted))               // if not in IBD whitelisted won't be checked
            {
                HeadersPayload headers    = new HeadersPayload();
                var            highestPow = SharedState.HighestValidatedPoW;
                highestPow = Chain.GetBlock(highestPow.HashBlock);
                var fork = Chain.FindFork(getheaders.BlockLocators);

                if (fork != null)
                {
                    if (highestPow == null || fork.Height > highestPow.Height)
                    {
                        fork = null;                         //fork not yet validated
                    }
                    if (fork != null)
                    {
                        foreach (var header in Chain.EnumerateToTip(fork).Skip(1))
                        {
                            if (header.Height > highestPow.Height)
                            {
                                break;
                            }
                            headers.Headers.Add(header.Header);
                            if (header.HashBlock == getheaders.HashStop || headers.Headers.Count == 2000)
                            {
                                break;
                            }
                        }
                    }
                }
                AttachedNode.SendMessageAsync(headers);
            }

            // == HeadersPayload ==
            // represents the peers height from our point view
            // this updates the pending tip parameter which is the
            // peers current best validated height
            // if the peer's height is higher Chain.Tip is updated to have
            // the most PoW header
            // is sent in response to GetHeadersPayload or is solicited by the
            // peer when a new block is validated (and not in IBD)

            var newheaders       = message.Message.Payload as HeadersPayload;
            var pendingTipBefore = GetPendingTipOrChainTip();

            if (newheaders != null && CanSync)
            {
                // TODO: implement MAX_HEADERS_RESULTS in NBitcoin.HeadersPayload

                var tip = GetPendingTipOrChainTip();
                foreach (var header in newheaders.Headers)
                {
                    var prev = tip.FindAncestorOrSelf(header.HashPrevBlock);
                    if (prev == null)
                    {
                        break;
                    }
                    tip = new ChainedBlock(header, header.GetHash(), prev);
                    var validated = Chain.GetBlock(tip.HashBlock) != null || tip.Validate(AttachedNode.Network);
                    validated &= !SharedState.IsMarkedInvalid(tip.HashBlock);
                    if (!validated)
                    {
                        invalidHeaderReceived = true;
                        break;
                    }
                    _PendingTip = tip;
                }

                if (_PendingTip.ChainWork > Chain.Tip.ChainWork)
                {
                    Chain.SetTip(_PendingTip);
                }

                var chainedPendingTip = Chain.GetBlock(_PendingTip.HashBlock);
                if (chainedPendingTip != null)
                {
                    _PendingTip = chainedPendingTip;                     //This allows garbage collection to collect the duplicated pendingtip and ancestors
                }

                if (newheaders.Headers.Count != 0 && pendingTipBefore.HashBlock != GetPendingTipOrChainTip().HashBlock)
                {
                    TrySync();
                }

                Interlocked.Decrement(ref _SynchingCount);
            }

            act();
        }
예제 #2
0
        void Intercept(IncomingMessage message, Action act)
        {
            var inv = message.Message.Payload as InvPayload;

            if (inv != null)
            {
                if (inv.Inventory.Any(i => ((i.Type & InventoryType.MSG_BLOCK) != 0) && !Chain.Contains(i.Hash)))
                {
                    _Refresh.Dispose();                     //No need of periodical refresh, the peer is notifying us
                    if (AutoSync)
                    {
                        TrySync();
                    }
                }
            }

            var getheaders = message.Message.Payload as GetHeadersPayload;

            if (getheaders != null && CanRespondToGetHeaders && !StripHeader)
            {
                HeadersPayload headers    = new HeadersPayload();
                var            highestPow = SharedState.HighestValidatedPoW;
                highestPow = highestPow == null ? null : Chain.GetBlock(highestPow.HashBlock);
                var fork = Chain.FindFork(getheaders.BlockLocators);
                if (fork != null)
                {
                    if (highestPow != null && fork.Height > highestPow.Height)
                    {
                        fork = null;                         //fork not yet validated
                    }
                    if (fork != null)
                    {
                        foreach (var header in Chain.EnumerateToTip(fork).Skip(1))
                        {
                            if (highestPow != null && header.Height > highestPow.Height)
                            {
                                break;
                            }
                            headers.Headers.Add(header.Header);
                            if (header.HashBlock == getheaders.HashStop || headers.Headers.Count == 2000)
                            {
                                break;
                            }
                        }
                    }
                }
                AttachedNode.SendMessageAsync(headers);
            }

            var newheaders       = message.Message.Payload as HeadersPayload;
            var pendingTipBefore = GetPendingTipOrChainTip();

            if (newheaders != null && CanSync)
            {
                var tip = GetPendingTipOrChainTip();
                foreach (var header in newheaders.Headers)
                {
                    var prev = tip.FindAncestorOrSelf(header.HashPrevBlock);
                    if (prev == null)
                    {
                        break;
                    }
                    tip = new ChainedBlock(header, header.GetHash(), prev);
                    var validated = Chain.GetBlock(tip.HashBlock) != null || (SkipPoWCheck || tip.Validate(AttachedNode.Network));
                    validated &= !SharedState.IsMarkedInvalid(tip.HashBlock);
                    if (!validated)
                    {
                        invalidHeaderReceived = true;
                        break;
                    }
                    _PendingTip = tip;
                }

                bool isHigherBlock = false;
                if (SkipPoWCheck)
                {
                    isHigherBlock = _PendingTip.Height > Chain.Tip.Height;
                }
                else
                {
                    isHigherBlock = _PendingTip.GetChainWork(true) > Chain.Tip.GetChainWork(true);
                }

                if (isHigherBlock)
                {
                    Chain.SetTip(_PendingTip);
                    if (StripHeader)
                    {
                        _PendingTip.StripHeader();
                    }
                }

                var chainedPendingTip = Chain.GetBlock(_PendingTip.HashBlock);
                if (chainedPendingTip != null)
                {
                    _PendingTip = chainedPendingTip;                     //This allows garbage collection to collect the duplicated pendingtip and ancestors
                }
                if (newheaders.Headers.Count != 0 && pendingTipBefore.HashBlock != GetPendingTipOrChainTip().HashBlock)
                {
                    TrySync();
                }
                Interlocked.Decrement(ref _SynchingCount);
            }

            act();
        }