Beispiel #1
0
        void AttachedNode_MessageReceived(Node node, IncomingMessage message)
        {
            var filterload = message.Message.Payload as FilterLoadPayload;

            if (filterload != null)
            {
                _Filter = filterload.Object;
            }
            var getdata = message.Message.Payload as GetDataPayload;

            if (getdata != null)
            {
                foreach (var inv in getdata.Inventory)
                {
                    if (inv.Type == InventoryType.MSG_FILTERED_BLOCK && _Filter != null)
                    {
                        var merkle = new MerkleBlock(_Blocks[inv.Hash], _Filter);
                        AttachedNode.SendMessageAsync(new MerkleBlockPayload(merkle));
                        foreach (var tx in merkle.PartialMerkleTree.GetMatchedTransactions())
                        {
                            if (_Known.TryAdd(tx, tx))
                            {
                                AttachedNode.SendMessageAsync(new InvPayload(InventoryType.MSG_TX, tx));
                            }
                        }
                    }
                    if (inv.Type == InventoryType.MSG_TX)
                    {
                        AttachedNode.SendMessageAsync(new TxPayload(_Transactions[inv.Hash]));
                    }
                }
            }
        }
Beispiel #2
0
 internal void StartDownload(uint256 block)
 {
     if (_Puller._Map.TryAdd(block, this))
     {
         _PendingDownloads.TryAdd(block, block);
         AttachedNode.SendMessageAsync(new GetDataPayload(new InventoryVector(AttachedNode.AddSupportedOptions(InventoryType.MSG_BLOCK), block)));
     }
 }
Beispiel #3
0
        void AttachedNode_StateChanged(Node node, NodeState oldState)
        {
            //TODO: to check: don't send to self

            if (node.State == NodeState.HandShaked && IsTipOld)
            {
                AttachedNode.SendMessageAsync(new GetTipPayload());
            }
        }
Beispiel #4
0
 //Caller should add to the puller map
 internal void StartDownload(GetDataPayload getDataPayload)
 {
     foreach (var inv in getDataPayload.Inventory)
     {
         inv.Type = AttachedNode.AddSupportedOptions(inv.Type);
         _PendingDownloads.TryAdd(inv.Hash, inv.Hash);
     }
     AttachedNode.SendMessageAsync(getDataPayload);
 }
Beispiel #5
0
 private void BroadcastCore(Transaction obj)
 {
     if (_Builder.Broadcast)
     {
         if (_Filter != null && _Filter.IsRelevantAndUpdate(obj) && _Known.TryAdd(obj.GetHash(), obj.GetHash()))
         {
             AttachedNode.SendMessageAsync(new InvPayload(obj));
         }
     }
 }
Beispiel #6
0
 void _Builder_NewTransaction(Transaction obj)
 {
     _Transactions.AddOrReplace(obj.GetHash(), obj);
     if (_Builder.Broadcast)
     {
         if (_Filter != null && _Filter.IsRelevantAndUpdate(obj) && _Known.TryAdd(obj.GetHash(), obj.GetHash()))
         {
             AttachedNode.SendMessageAsync(new InvPayload(obj));
         }
     }
 }
Beispiel #7
0
 /// <summary>
 /// Asynchronously try to sync the chain
 /// </summary>
 public void TrySync()
 {
     if (AttachedNode.State == NodeState.HandShaked && CanSync && !invalidHeaderReceived)
     {
         Interlocked.Increment(ref _SynchingCount);
         AttachedNode.SendMessageAsync(new GetHeadersPayload()
         {
             BlockLocators = GetPendingTip().GetLocator()
         });
     }
 }
Beispiel #8
0
 void _Builder_NewBlock(Block obj)
 {
     _Blocks.AddOrReplace(obj.GetHash(), obj);
     foreach (var tx in obj.Transactions)
     {
         _Transactions.TryAdd(tx.GetHash(), tx);
     }
     if (_Builder.Broadcast)
     {
         AttachedNode.SendMessageAsync(new InvPayload(obj));
     }
 }
Beispiel #9
0
        void AttachedNode_MessageReceived(Node node, IncomingMessage message)
        {
            var filterload = message.Message.Payload as FilterLoadPayload;

            if (filterload != null)
            {
                _Filter = filterload.Object;
            }
            var filteradd = message.Message.Payload as FilterAddPayload;

            if (filteradd != null)
            {
                _Filter.Insert(filteradd.Data);
            }
            var getdata = message.Message.Payload as GetDataPayload;

            if (getdata != null)
            {
                foreach (var inv in getdata.Inventory)
                {
                    if (inv.Type == InventoryType.MSG_FILTERED_BLOCK && _Filter != null)
                    {
                        var merkle = new MerkleBlock(_Blocks[inv.Hash], _Filter);
                        AttachedNode.SendMessageAsync(new MerkleBlockPayload(merkle));
                        foreach (var tx in merkle.PartialMerkleTree.GetMatchedTransactions())
                        {
                            if (_Known.TryAdd(tx, tx))
                            {
                                AttachedNode.SendMessageAsync(new InvPayload(InventoryType.MSG_TX, tx));
                            }
                        }
                    }
                    var found = FindTransaction(inv.Hash);
                    if (inv.Type == InventoryType.MSG_TX && found != null)
                    {
                        AttachedNode.SendMessageAsync(new TxPayload(found));
                    }
                }
            }
            var mempool = message.Message.Payload as MempoolPayload;

            if (mempool != null)
            {
                foreach (var tx in _Builder.Mempool)
                {
                    BroadcastCore(tx.Value);
                }
            }
        }
Beispiel #10
0
        public void AskBlocks()
        {
            if (AttachedNode.State != NodeState.HandShaked)
            {
                return;
            }
            var pendingTip = AttachedNode.Behaviors.Find <ChainBehavior>().PendingTip;

            if (pendingTip == null || pendingTip.Height < AttachedNode.PeerVersion.StartHeight)
            {
                return;
            }
            if (_InFlights.Count != 0)
            {
                return;
            }
            var currentLocation = _CurrentLocation ?? new BlockLocator()
            {
                Blocks = { Chain.GetBlock(StartHeight).HashBlock }
            };;
            var currentBlock = Chain.FindFork(currentLocation);

            if (currentBlock.Height < StartHeight)
            {
                currentBlock = Chain.GetBlock(StartHeight) ?? pendingTip;
            }

            //Up to date
            if (pendingTip.HashBlock == currentBlock.HashBlock)
            {
                return;
            }

            var toDownload = pendingTip.EnumerateToGenesis().TakeWhile(b => b.HashBlock != currentBlock.HashBlock).ToArray();

            Array.Reverse(toDownload);
            var invs = toDownload.Take(10)
                       .Select(b => new InventoryVector(AttachedNode.AddSupportedOptions(InventoryType.MSG_BLOCK), b.HashBlock))
                       .Where(b => _InFlights.TryAdd(b.Hash, new Download()))
                       .ToArray();

            if (invs.Length != 0)
            {
                AttachedNode.SendMessageAsync(new GetDataPayload(invs));
                Runtime.Repository.SetIndexProgress(currentLocation);
            }
        }
 protected override void AttachCore()
 {
     _Refresh = new Timer(o =>
     {
         TrySync();
     }, null, 0, (int)TimeSpan.FromMinutes(10).TotalMilliseconds);
     RegisterDisposable(_Refresh);
     if (AttachedNode.State == NodeState.Connected)
     {
         AttachedNode.MyVersion.StartHeight = Chain.Height;
     }
     AttachedNode.StateChanged += AttachedNode_StateChanged;
     RegisterDisposable(AttachedNode.Filters.Add(Intercept));
     if (AttachedNode.State == NodeState.HandShaked)
     {
         AttachedNode.SendMessageAsync(new SendHeadersPayload());
         TrySync();
     }
 }
Beispiel #12
0
        void AttachedNode_MessageReceived(Node node, IncomingMessage message)
        {
            var filterload = message.Message.Payload as FilterLoadPayload;

            if (filterload != null)
            {
                _Filter = filterload.Object;
            }
            var filteradd = message.Message.Payload as FilterAddPayload;

            if (filteradd != null)
            {
                _Filter.Insert(filteradd.Data);
            }
            var getdata = message.Message.Payload as GetDataPayload;

            if (getdata != null)
            {
                foreach (var inv in getdata.Inventory)
                {
                    if (inv.Type == InventoryType.MSG_FILTERED_BLOCK && _Filter != null)
                    {
                        var merkle = new MerkleBlock(_Blocks[inv.Hash], _Filter);
                        AttachedNode.SendMessageAsync(new MerkleBlockPayload(merkle));
                        foreach (var tx in merkle.PartialMerkleTree.GetMatchedTransactions())
                        {
                            if (_Known.TryAdd(tx, tx))
                            {
                                AttachedNode.SendMessageAsync(new InvPayload(InventoryType.MSG_TX, tx));
                            }
                        }
                    }
                    var found = FindTransaction(inv.Hash);
                    if (inv.Type == InventoryType.MSG_TX && found != null)
                    {
                        AttachedNode.SendMessageAsync(new TxPayload(found));
                    }
                }
            }
            var mempool = message.Message.Payload as MempoolPayload;

            if (mempool != null)
            {
                foreach (var tx in _Builder.Mempool)
                {
                    BroadcastCore(tx.Value);
                }
            }

            var invs = message.Message.Payload as InvPayload;

            if (invs != null)
            {
                node.SendMessageAsync(new GetDataPayload(invs.ToArray()));
            }

            var txPayload = message.Message.Payload as TxPayload;

            if (txPayload != null)
            {
                if (!_ReceivedTransactions.TryAdd(txPayload.Object.GetHash(), txPayload.Object))
                {
                    node.SendMessageAsync(new RejectPayload()
                    {
                        Hash    = txPayload.Object.GetHash(),
                        Code    = RejectCode.DUPLICATE,
                        Message = "tx"
                    });
                }
                else
                {
                    foreach (var other in Nodes.Where(n => n != node))
                    {
                        other.SendMessageAsync(new InvPayload(txPayload.Object));
                    }
                }
            }
        }
Beispiel #13
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();
        }
Beispiel #14
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();
        }
Beispiel #15
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) && !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)
            {
                HeadersPayload headers = new HeadersPayload();
                var            fork    = Chain.FindFork(getheaders.BlockLocators);
                if (fork != null)
                {
                    foreach (var header in Chain.EnumerateToTip(fork).Skip(1))
                    {
                        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 = GetPendingTip();

            if (newheaders != null && CanSync)
            {
                var tip = GetPendingTip();
                foreach (var header in newheaders.Headers)
                {
                    var prev = tip.FindAncestorOrSelf(header.HashPrevBlock);
                    if (prev == null)
                    {
                        break;
                    }
                    tip = new ChainedBlock(header, header.GetHash(), prev);
                    if (!AttachedNode.IsTrusted)
                    {
                        var validated = Chain.GetBlock(tip.HashBlock) != null || tip.Validate(AttachedNode.Network);
                        if (!validated)
                        {
                            invalidHeaderReceived = true;
                            break;
                        }
                    }
                    _PendingTip = tip;
                }
                if (_PendingTip.Height > Chain.Tip.Height)
                {
                    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 != GetPendingTip().HashBlock)
                {
                    TrySync();
                }
                Interlocked.Decrement(ref _SynchingCount);
            }

            act();
        }