Ejemplo n.º 1
0
 protected override void ProcessTx(TxPayload payload)
 {
     if (!MempoolService.TrustedNodeMode)
     {
         base.ProcessTx(payload);
     }
 }
Ejemplo n.º 2
0
        protected virtual void ProcessTx(TxPayload payload)
        {
            Transaction transaction = payload.Object;

            transaction.PrecomputeHash(false, true);
            MempoolService.Process(transaction);
        }
        /// <summary>
        /// Handler for processing node messages.
        /// Handles the following message payloads: TxPayload, MempoolPayload, GetDataPayload, InvPayload.
        /// </summary>
        /// <param name="node">Node sending the message.</param>
        /// <param name="message">Incoming message.</param>
        private Task AttachedNode_MessageReceivedAsync(Node node, IncomingMessage message)
        {
            TxPayload txPayload = message.Message.Payload as TxPayload;

            if (txPayload != null)
            {
                return(this.ProcessTxPayloadAsync(node, txPayload));
            }

            MempoolPayload mempoolPayload = message.Message.Payload as MempoolPayload;

            if (mempoolPayload != null)
            {
                return(this.SendMempoolPayload(node, mempoolPayload));
            }

            GetDataPayload getDataPayload = message.Message.Payload as GetDataPayload;

            if (getDataPayload != null)
            {
                return(this.ProcessGetDataAsync(node, getDataPayload));
            }

            InvPayload invPayload = message.Message.Payload as InvPayload;

            if (invPayload != null)
            {
                return(this.ProcessInvAsync(node, invPayload));
            }

            return(Task.CompletedTask);
        }
Ejemplo n.º 4
0
        void NewNodeMessage(IncomingMessage message)
        {
            if (message.Message.Payload is VerAckPayload)
            {
                _Nodes.Add(message.Node);
            }
            if (message.Message.Payload is InvPayload)
            {
                InvPayload invPayload = (InvPayload)message.Message.Payload;
                message.Node.SendMessage(new GetDataPayload(invPayload.Inventory.ToArray()));
            }
            if (message.Message.Payload is TxPayload)
            {
                TxPayload txPayload = (TxPayload)message.Message.Payload;
                _ReceivedTransactions.AddOrUpdate(txPayload.Object.GetHash(), txPayload.Object, (k, v) => v);
            }
            if (message.Message.Payload is GetHeadersPayload)
            {
                var headers  = (GetHeadersPayload)message.Message.Payload;
                var fork     = _Server.ChainBuilder.Chain.FindFork(headers.BlockLocators);
                var response =
                    _Server.ChainBuilder.Chain
                    .ToEnumerable(true)
                    .TakeWhile(f => f.HashBlock != fork.HashBlock && f.HashBlock != headers.HashStop)
                    .Select(f => f.Header)
                    .ToArray();
                HeadersPayload res = new HeadersPayload();
                res.Headers.AddRange(response);
                message.Node.SendMessage(res);
            }

            if (message.Message.Payload is GetDataPayload)
            {
                Transaction tx;
                Block       block;
                var         getData = message.Message.Payload as GetDataPayload;
                foreach (var inv in getData.Inventory)
                {
                    if (inv.Type == InventoryType.MSG_TX)
                    {
                        if (_Transactions.TryGetValue(inv.Hash, out tx))
                        {
                            message.Node.SendMessage(new TxPayload(tx));
                        }
                    }
                    if (inv.Type == InventoryType.MSG_BLOCK)
                    {
                        if (_Blocks.TryGetValue(inv.Hash, out block))
                        {
                            message.Node.SendMessage(new BlockPayload(block));
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
        public void TryDeserialize_FailTest(FastStreamReader stream, MockDeserializableTx tx, string expErr)
        {
            TxPayload pl = new TxPayload()
            {
                Tx = tx
            };

            bool b = pl.TryDeserialize(stream, out string error);

            Assert.False(b);
            Assert.Equal(expErr, error);
            // Mock tx has its own tests.
        }
Ejemplo n.º 6
0
        private void ProcessTxPayload(TxPayload txPayload)
        {
            Transaction transaction = txPayload.Obj;
            uint256     trxHash     = transaction.GetHash();

            if (this.notifiedTransactions.TransactionsReceived.ContainsKey(trxHash))
            {
                return;
            }

            // send the transaction to the notifier
            this.signals.Publish(new TransactionReceived(transaction));
            this.notifiedTransactions.TransactionsReceived.TryAdd(trxHash, trxHash);
        }
        /// <inheritdoc />
        public bool SendTransaction(string transactionHex)
        {
            // TODO move this to a behavior on the full node
            // parse transaction
            Transaction transaction = Transaction.Parse(transactionHex);
            TxPayload   payload     = new TxPayload(transaction);

            foreach (var node in this.connectionManager.ConnectedNodes)
            {
                node.SendMessage(payload);
            }

            return(true);
        }
Ejemplo n.º 8
0
        private void ProcessTxPayload(TxPayload txPayload)
        {
            var transaction = txPayload.Obj;
            var trxHash     = transaction.GetHash();

            if (this.notifiedTransactions.TransactionsReceived.ContainsKey(trxHash))
            {
                return;
            }

            // send the transaction to the notifier
            this.transactionNotification.Notify(transaction);
            this.notifiedTransactions.TransactionsReceived.TryAdd(trxHash, trxHash);
        }
Ejemplo n.º 9
0
        public void TryDeserializeTest()
        {
            TxPayload pl = new TxPayload()
            {
                Tx = new MockDeserializableTx(0, 3)
            };
            FastStreamReader stream = new FastStreamReader(new byte[3]);
            bool             b      = pl.TryDeserialize(stream, out string error);

            Assert.True(b, error);
            Assert.Null(error);
            // Mock tx has its own tests.
            Assert.Equal(PayloadType.Tx, pl.PayloadType);
        }
        /// <summary>
        /// Processing of the transaction payload message from peer.
        /// Adds transaction from the transaction payload to the memory pool.
        /// </summary>
        /// <param name="peer">Peer sending the message.</param>
        /// <param name="transactionPayload">The payload for the message.</param>
        private async Task ProcessTxPayloadAsync(INetworkPeer peer, TxPayload transactionPayload)
        {
            this.logger.LogTrace("({0}:'{1}',{2}.{3}:{4})", nameof(peer), peer.RemoteSocketEndpoint, nameof(transactionPayload), nameof(transactionPayload.Obj), transactionPayload?.Obj?.GetHash());
            Transaction trx     = transactionPayload.Obj;
            uint256     trxHash = trx.GetHash();

            // add to local filter
            lock (this.lockObject)
            {
                this.filterInventoryKnown.Add(trxHash);
            }
            this.logger.LogTrace("Added transaction ID '{0}' to known inventory filter.", trxHash);

            var state = new MempoolValidationState(true);

            if (!await this.orphans.AlreadyHaveAsync(trxHash) && await this.validator.AcceptToMemoryPool(state, trx))
            {
                await this.validator.SanityCheck();

                this.RelayTransaction(trxHash);

                this.signals.SignalTransaction(trx);

                long mmsize = state.MempoolSize;
                long memdyn = state.MempoolDynamicSize;

                this.logger.LogInformation("Transaction ID '{0}' accepted to memory pool from peer '{1}' (poolsz {2} txn, {3} kb).", trxHash, peer.RemoteSocketEndpoint, mmsize, memdyn / 1000);

                await this.orphans.ProcessesOrphansAsync(this, trx);
            }
            else if (state.MissingInputs)
            {
                this.orphans.ProcessesOrphansMissingInputs(peer, trx);
            }
            else
            {
                if (!trx.HasWitness && state.CorruptionPossible)
                {
                }

                // TODO: Implement Processes whitelistforcerelay
            }

            if (state.IsInvalid)
            {
                this.logger.LogInformation("Transaction ID '{0}' from peer '{1}' was not accepted. Invalid state of '{2}'.", trxHash, peer.RemoteSocketEndpoint, state);
            }

            this.logger.LogTrace("(-)");
        }
Ejemplo n.º 11
0
        public void SerializeTest()
        {
            TxPayload pl = new TxPayload()
            {
                Tx = new MockSerializableTx(new byte[] { 1, 2, 3 })
            };

            FastStream stream = new FastStream();

            pl.Serialize(stream);
            byte[] actual   = pl.Serialize();
            byte[] expected = new byte[] { 1, 2, 3 };

            Assert.Equal(expected, stream.ToByteArray());
            Assert.Equal(expected, actual);
        }
Ejemplo n.º 12
0
        private async Task ProcessTxPayloadAsync(Node node, TxPayload transactionPayload)
        {
            var trx     = transactionPayload.Object;
            var trxHash = trx.GetHash();

            // add to local filter
            await this.manager.MempoolScheduler.WriteAsync(() => this.filterInventoryKnown.TryAdd(trxHash, trxHash));

            var state = new MempoolValidationState(true);

            if (!await this.orphans.AlreadyHave(trxHash) && await this.validator.AcceptToMemoryPool(state, trx))
            {
                await this.validator.SanityCheck();

                await this.RelayTransaction(trxHash).ConfigureAwait(false);

                this.signals.Transactions.Broadcast(trx);

                var mmsize = state.MempoolSize;
                var memdyn = state.MempoolDynamicSize;

                Logging.Logs.Mempool.LogInformation(
                    $"AcceptToMemoryPool: peer={node.Peer.Endpoint}: accepted {trxHash} (poolsz {mmsize} txn, {memdyn/1000} kb)");

                await this.orphans.ProcessesOrphans(this, trx);
            }
            else if (state.MissingInputs)
            {
                await this.orphans.ProcessesOrphansMissingInputs(node, trx);
            }
            else
            {
                if (!trx.HasWitness && state.CorruptionPossible)
                {
                }

                // TODO: Implement Processes whitelistforcerelay
            }

            if (state.IsInvalid)
            {
                Logging.Logs.Mempool.LogInformation($"{trxHash} from peer={node.Peer.Endpoint} was not accepted: {state}");
            }
        }
Ejemplo n.º 13
0
 void _SenderNode_MessageReceived(Node node, IncomingMessage message)
 {
     if (message.Message.Payload is GetDataPayload)
     {
         var getData = (GetDataPayload)message.Message.Payload;
         foreach (var data in getData.Inventory)
         {
             if (data.Type == InventoryType.MSG_TX && _BroadcastedTransactions.ContainsKey(data.Hash))
             {
                 var result = _BroadcastedTransactions[data.Hash];
                 var tx     = new TxPayload(result.Transaction);
                 node.SendMessage(tx);
                 ListenerTrace.Info("Broadcasted " + data.Hash);
                 try
                 {
                     Configuration.GetBroadcastedTransactionsListenable().CloudTable.Execute(TableOperation.Delete(result.ToEntity()));
                 }
                 catch (StorageException)
                 {
                 }
             }
         }
     }
     if (message.Message.Payload is RejectPayload)
     {
         var     reject = (RejectPayload)message.Message.Payload;
         uint256 txId   = reject.Hash;
         if (txId != null && _BroadcastedTransactions.ContainsKey(txId))
         {
             ListenerTrace.Info("Broadcasted transaction rejected (" + reject.Code + ") " + txId);
             DeleteBroadcasted(txId);
             if (reject.Code != RejectCode.DUPLICATE)
             {
                 UpdateBroadcastState(txId, reject.Code.ToString());
             }
         }
     }
     if (message.Message.Payload is PongPayload)
     {
         ListenerTrace.Verbose("Pong");
     }
 }
Ejemplo n.º 14
0
            void AttachedNode_MessageReceived(Node node, IncomingMessage message)
            {
                TxPayload txPayload = message.Message.Payload as TxPayload;

                if (txPayload != null)
                {
                    Transaction tx;
                    var         hash = txPayload.Object.GetHash();
                    if (_Wallet._BroadcastedTransaction.TryRemove(hash, out tx))
                    {
                        _Broadcasting.TryRemove(hash, out tx);
                        _Wallet.OnTransactionBroadcasted(tx, node);
                    }
                }
                RejectPayload reject = message.Message.Payload as RejectPayload;

                if (reject != null)
                {
                    Transaction tx;
                    if (_Broadcasting.TryRemove(reject.Hash, out tx))
                    {
                        _Wallet.OnTransactionRejected(tx, node);
                    }
                }

                GetDataPayload getData = message.Message.Payload as GetDataPayload;

                if (getData != null)
                {
                    foreach (var inventory in getData.Inventory.Where(i => i.Type == InventoryType.MSG_TX))
                    {
                        Transaction tx;
                        if (_Broadcasting.TryRemove(inventory.Hash, out tx))
                        {
                            node.SendMessageAsync(new TxPayload(tx));
                        }
                    }
                }
            }
Ejemplo n.º 15
0
        private async Task ProcessGetDataAsync(Node node, GetDataPayload payload)
        {
            if (payload.Inventory.Count > MaxInvSize)
            {
                Logger.LogDebug($"Received inventory too big. {nameof(MaxInvSize)}: {MaxInvSize}, Node: {node.RemoteSocketEndpoint}");
                return;
            }

            foreach (var inv in payload.Inventory.Where(inv => inv.Type.HasFlag(InventoryType.MSG_TX)))
            {
                if (MempoolService.TryGetFromBroadcastStore(inv.Hash, out TransactionBroadcastEntry entry))                 // If we have the transaction to be broadcasted then broadcast it now.
                {
                    if (entry.NodeRemoteSocketEndpoint != node.RemoteSocketEndpoint.ToString())
                    {
                        continue;                         // Would be strange. It could be some kind of attack.
                    }

                    try
                    {
                        var txPayload = new TxPayload(entry.Transaction);
                        if (!node.IsConnected)
                        {
                            Logger.LogInfo($"Could not serve transaction. Node ({node.RemoteSocketEndpoint}) is not connected anymore: {entry.TransactionId}.");
                        }
                        else
                        {
                            await node.SendMessageAsync(txPayload).ConfigureAwait(false);

                            entry.MakeBroadcasted();
                            Logger.LogInfo($"Successfully served transaction to node ({node.RemoteSocketEndpoint}): {entry.TransactionId}.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogInfo(ex);
                    }
                }
            }
        }
        /// <summary>
        /// Handler for processing node messages.
        /// Handles the following message payloads: TxPayload, MempoolPayload, GetDataPayload, InvPayload.
        /// </summary>
        /// <param name="node">Node sending the message.</param>
        /// <param name="message">Incoming message.</param>
        private Task ProcessMessageAsync(Node node, IncomingMessage message)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}')", nameof(node), node.RemoteSocketEndpoint, nameof(message), message.Message.Command);

            TxPayload txPayload = message.Message.Payload as TxPayload;

            if (txPayload != null)
            {
                this.logger.LogTrace("(-)[TX_PAYLOAD]");
                return(this.ProcessTxPayloadAsync(node, txPayload));
            }

            MempoolPayload mempoolPayload = message.Message.Payload as MempoolPayload;

            if (mempoolPayload != null)
            {
                this.logger.LogTrace("(-)[MEMPOOL_PAYLOAD]");
                return(this.SendMempoolPayloadAsync(node, mempoolPayload));
            }

            GetDataPayload getDataPayload = message.Message.Payload as GetDataPayload;

            if (getDataPayload != null)
            {
                this.logger.LogTrace("(-)[GET_DATA_PAYLOAD]");
                return(this.ProcessGetDataAsync(node, getDataPayload));
            }

            InvPayload invPayload = message.Message.Payload as InvPayload;

            if (invPayload != null)
            {
                this.logger.LogTrace("(-)[INV_PAYLOAD]");
                return(this.ProcessInvAsync(node, invPayload));
            }

            this.logger.LogTrace("(-)");
            return(Task.CompletedTask);
        }
Ejemplo n.º 17
0
        /// <inheritdoc />
        public bool SendTransaction(string transactionHex)
        {
            Guard.NotEmpty(transactionHex, nameof(transactionHex));

            // TODO move this to a behavior to a dedicated interface
            // parse transaction
            Transaction transaction = Transaction.Parse(transactionHex);

            // replace this we a dedicated WalletBroadcast interface
            // in a fullnode implementation this will validate with the
            // mempool and broadcast, in a lightnode this will push to
            // the wallet and then broadcast (we might add some basic validation
            if (this.mempoolValidator == null)
            {
                this.ProcessTransaction(transaction);
            }
            else
            {
                var state = new MempoolValidationState(false);
                if (!this.mempoolValidator.AcceptToMemoryPool(state, transaction).GetAwaiter().GetResult())
                {
                    return(false);
                }
                this.ProcessTransaction(transaction);
            }

            // broadcast to peers
            TxPayload payload = new TxPayload(transaction);

            foreach (var node in this.connectionManager.ConnectedNodes)
            {
                node.SendMessage(payload);
            }

            // we might want to create a behaviour that tracks how many times
            // the broadcast trasnactions was sent back to us by other peers
            return(true);
        }
Ejemplo n.º 18
0
        private void ProcessTx(TxPayload payload)
        {
            Transaction transaction = payload.Object;

            MemPoolService.OnTransactionReceived(new SmartTransaction(transaction, Height.MemPool));
        }
Ejemplo n.º 19
0
        public static void Send(ConnectionType connectionType, TransactionInfo transactionInfo, int tryTimes = 1)
        {
            var monitor = new HttpMonitor(transactionInfo.Network);

            if (connectionType == ConnectionType.Http)
            {
                var client      = new QBitNinjaClient(Convert.ToNBitcoinNetwork(transactionInfo.Network));
                var transaction = FindTransaction(transactionInfo);

                var broadcastResponse = client.Broadcast(transaction).Result;
                if (!broadcastResponse.Success)
                {
                    throw new Exception($"ErrorCode: {broadcastResponse.Error.ErrorCode}" + Environment.NewLine
                                        + broadcastResponse.Error.Reason);
                }
            }
            if (connectionType == ConnectionType.RandomNode)
            {
                var parameters = new NodeConnectionParameters();
                var group      = new NodesGroup(Convert.ToNBitcoinNetwork(transactionInfo.Network), parameters, new NodeRequirement
                {
                    RequiredServices = NodeServices.Nothing
                })
                {
                    MaximumNodeConnection = 1
                };
                group.Connect();

                while (group.ConnectedNodes.Count == 0)
                {
                    Thread.Sleep(100);
                }
                var transaction = FindTransaction(transactionInfo);
                var payload     = new TxPayload(transaction);
                group.ConnectedNodes.First().SendMessage(payload);
            }

            for (var i = 0; i < 10; i++)
            {
                try
                {
                    monitor.GetTransactionInfo(transactionInfo.Id);
                }
                catch (NullReferenceException exception)
                {
                    if (exception.Message != "Transaction does not exists")
                    {
                        throw;
                    }
                    Thread.Sleep(1000);
                    continue;
                }
                if (i == 10)
                {
                    if (tryTimes == 1)
                    {
                        throw new Exception("Transaction has not been broadcasted, try again!");
                    }
                    Send(connectionType, transactionInfo, tryTimes - 1);
                }
                break;
            }
        }
        /// <summary>
        /// Processing of the transaction payload message from peer.
        /// Adds transaction from the transaction payload to the memory pool.
        /// </summary>
        /// <param name="peer">Peer sending the message.</param>
        /// <param name="transactionPayload">The payload for the message.</param>
        private async Task ProcessTxPayloadAsync(INetworkPeer peer, TxPayload transactionPayload)
        {
            // Stop processing the transaction early if we are in blocks only mode.
            if (this.isBlocksOnlyMode)
            {
                this.logger.LogInformation("Transaction sent in violation of protocol from peer '{0}'.", peer.RemoteSocketEndpoint);
                this.logger.LogTrace("(-)[BLOCKSONLY]");
                return;
            }

            Transaction trx     = transactionPayload.Obj;
            uint256     trxHash = trx.GetHash();

            // add to local filter
            lock (this.lockObject)
            {
                this.filterInventoryKnown.Add(trxHash);
            }
            this.logger.LogTrace("Added transaction ID '{0}' to known inventory filter.", trxHash);

            var state = new MempoolValidationState(true);

            if (!await this.orphans.AlreadyHaveAsync(trxHash) && await this.validator.AcceptToMemoryPool(state, trx))
            {
                await this.validator.SanityCheck();

                this.RelayTransaction(trxHash);

                this.signals.SignalTransaction(trx);

                long mmsize = state.MempoolSize;
                long memdyn = state.MempoolDynamicSize;

                this.logger.LogInformation("Transaction ID '{0}' accepted to memory pool from peer '{1}' (poolsz {2} txn, {3} kb).", trxHash, peer.RemoteSocketEndpoint, mmsize, memdyn / 1000);

                await this.orphans.ProcessesOrphansAsync(this, trx);
            }
            else if (state.MissingInputs)
            {
                this.orphans.ProcessesOrphansMissingInputs(peer, trx);
            }
            else
            {
                // Do not use rejection cache for witness transactions or
                // witness-stripped transactions, as they can have been malleated.
                // See https://github.com/bitcoin/bitcoin/issues/8279 for details.
                if (!trx.HasWitness && !state.CorruptionPossible)
                {
                    this.orphans.AddToRecentRejects(trxHash);
                }

                // Always relay transactions received from whitelisted peers, even
                // if they were already in the mempool or rejected from it due
                // to policy, allowing the node to function as a gateway for
                // nodes hidden behind it.
                //
                // Never relay transactions that we would assign a non-zero DoS
                // score for, as we expect peers to do the same with us in that
                // case.
                if (this.isPeerWhitelistedForRelay)
                {
                    if (!state.IsInvalid)
                    {
                        this.logger.LogInformation("Force relaying transaction ID '{0}' from whitelisted peer '{1}'.", trxHash, peer.RemoteSocketEndpoint);
                        this.RelayTransaction(trxHash);
                    }
                    else
                    {
                        this.logger.LogInformation("Not relaying invalid transaction ID '{0}' from whitelisted peer '{1}' ({2}).", trxHash, peer.RemoteSocketEndpoint, state);
                    }
                }
            }

            if (state.IsInvalid)
            {
                this.logger.LogInformation("Transaction ID '{0}' from peer '{1}' was not accepted. Invalid state of '{2}'.", trxHash, peer.RemoteSocketEndpoint, state);
            }
        }
Ejemplo n.º 21
0
        public static async Task SendAsync(string baseAddress, ConnectionType connectionType, TransactionInfo transactionInfo, int tryTimes = 1)
        {
            var monitor = new HttpMonitor(baseAddress, transactionInfo.Network);

            if (connectionType == ConnectionType.Http)
            {
                var client      = new QBitNinjaClient(baseAddress, transactionInfo.Network.ToNBitcoinNetwork());
                var transaction = FindTransaction(transactionInfo);

                var broadcastResponse = await client.Broadcast(transaction).ConfigureAwait(false);

                if (!broadcastResponse.Success)
                {
                    throw new Exception($"ErrorCode: {broadcastResponse.Error.ErrorCode}" + Environment.NewLine
                                        + broadcastResponse.Error.Reason);
                }
            }
            if (connectionType == ConnectionType.RandomNode)
            {
                var parameters = new NodeConnectionParameters();
                var group      = new NodesGroup(transactionInfo.Network.ToNBitcoinNetwork(), parameters, new NodeRequirement
                {
                    RequiredServices = NodeServices.Nothing
                })
                {
                    MaximumNodeConnection = 1
                };
                group.Connect();

                while (group.ConnectedNodes.Count == 0)
                {
                    await Task.Delay(100).ConfigureAwait(false);
                }

                var transaction = FindTransaction(transactionInfo);
                var payload     = new TxPayload(transaction);
                group.ConnectedNodes.First().SendMessage(payload);
            }

            for (var i = 0; i < 10; i++)
            {
                try
                {
                    var result = await monitor.GetTransactionInfoAsync(transactionInfo.Id);
                }
                catch (NullReferenceException exception)
                {
                    if (exception.Message != "Transaction does not exists")
                    {
                        throw;
                    }
                    await Task.Delay(1000).ConfigureAwait(false);

                    continue;
                }
                if (i == 10)
                {
                    if (tryTimes == 1)
                    {
                        throw new Exception("Transaction has not been broadcasted, try again!");
                    }
                    await SendAsync(baseAddress, connectionType, transactionInfo, tryTimes - 1)
                    .ConfigureAwait(false);
                }
                break;
            }
        }
Ejemplo n.º 22
0
        private void ProcessTx(TxPayload payload)
        {
            Transaction transaction = payload.Object;

            MempoolService.Process(transaction);
        }
Ejemplo n.º 23
0
        private void ProcessTxPayload(TxPayload transactionPayload)
        {
            Transaction tx = transactionPayload.Object;

            MemPoolJob.TryAddNewTransaction(tx);
        }
Ejemplo n.º 24
0
        void node_MessageReceived(Node node, IncomingMessage message)
        {
            if (_KnownInvs.Count == 1000)
            {
                _KnownInvs.Clear();
            }
            if (message.Message.Payload is InvPayload)
            {
                var inv = (InvPayload)message.Message.Payload;
                foreach (var inventory in inv.Inventory)
                {
                    Transaction tx;
                    if (_Broadcasting.TryRemove(inventory.Hash, out tx))
                    {
                        ListenerTrace.Info("Broadcasted reached mempool " + inventory);
                    }
                }
                var getdata = new GetDataPayload(inv.Inventory.Where(i => i.Type == InventoryType.MSG_TX && _KnownInvs.TryAdd(i.Hash, i.Hash)).ToArray());
                foreach (var data in getdata.Inventory)
                {
                    data.Type = node.AddSupportedOptions(InventoryType.MSG_TX);
                }
                if (getdata.Inventory.Count > 0)
                {
                    node.SendMessageAsync(getdata);
                }
            }
            if (message.Message.Payload is TxPayload)
            {
                var tx = ((TxPayload)message.Message.Payload).Object;
                ListenerTrace.Verbose("Received Transaction " + tx.GetHash());
                _Indexer.IndexAsync(new TransactionEntry.Entity(tx.GetHash(), tx, null))
                .ContinueWith(HandleException);
                _Indexer.IndexOrderedBalanceAsync(tx)
                .ContinueWith(HandleException);
                Async(() =>
                {
                    var txId = tx.GetHash();
                    List <OrderedBalanceChange> balances;
                    using (_WalletsSlimLock.LockRead())
                    {
                        balances =
                            OrderedBalanceChange
                            .ExtractWalletBalances(txId, tx, null, null, int.MaxValue, _Wallets)
                            .AsEnumerable()
                            .ToList();
                    }
                    UpdateHDState(balances);

                    _Indexer.IndexAsync(balances)
                    .ContinueWith(HandleException);


                    Task notify = null;
                    using (_SubscriptionSlimLock.LockRead())
                    {
                        var topic = Configuration.Topics.SendNotifications;

                        notify = Task.WhenAll(_Subscriptions
                                              .GetNewTransactions()
                                              .Select(t => topic.AddAsync(new Notify()
                        {
                            SendAndForget = true,
                            Notification  = new Notification()
                            {
                                Subscription = t,
                                Data         = new NewTransactionNotificationData()
                                {
                                    TransactionId = txId
                                }
                            }
                        })).ToArray());
                    }
                    notify.Wait();
                });
                var unused = Configuration.Topics.NewTransactions.AddAsync(tx)
                             .ContinueWith(HandleException);
            }

            if (message.Message.Payload is BlockPayload)
            {
                var block   = ((BlockPayload)message.Message.Payload).Object;
                var blockId = block.GetHash();

                List <OrderedBalanceChange> balances = null;
                using (_WalletsSlimLock.LockRead())
                {
                    balances = block.Transactions.SelectMany(tx => OrderedBalanceChange.ExtractWalletBalances(null, tx, null, null, 0, _Wallets)).ToList();
                }
                UpdateHDState(balances);
            }

            if (message.Message.Payload is HeadersPayload)
            {
                if (_Chain.Tip.HashBlock != _LastChainTip)
                {
                    var header = _Chain.Tip.Header;
                    _LastChainTip = _Chain.Tip.HashBlock;

                    Configuration.Indexer.CreateIndexer().IndexChain(_Chain);

                    Async(() =>
                    {
                        CancellationTokenSource cancel = new CancellationTokenSource(TimeSpan.FromMinutes(30));
                        var repo = new CacheBlocksRepository(new NodeBlocksRepository(node));
                        TryLock(_LockBlocks, () =>
                        {
                            new IndexBlocksTask(Configuration.Indexer)
                            {
                                EnsureIsSetup = false,
                            }.Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Blocks), repo, _Chain)
                            {
                                CancellationToken = cancel.Token
                            }, _Indexer.TaskScheduler);
                        });
                        TryLock(_LockTransactions, () =>
                        {
                            new IndexTransactionsTask(Configuration.Indexer)
                            {
                                EnsureIsSetup = false
                            }
                            .Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Transactions), repo, _Chain)
                            {
                                CancellationToken = cancel.Token
                            }, _Indexer.TaskScheduler);
                        });
                        TryLock(_LockWallets, () =>
                        {
                            using (_WalletsSlimLock.LockRead())
                            {
                                new IndexBalanceTask(Configuration.Indexer, _Wallets)
                                {
                                    EnsureIsSetup = false
                                }
                                .Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Wallets), repo, _Chain)
                                {
                                    CancellationToken = cancel.Token
                                }, _Indexer.TaskScheduler);
                            }
                        });
                        TryLock(_LockBalance, () =>
                        {
                            new IndexBalanceTask(Configuration.Indexer, null)
                            {
                                EnsureIsSetup = false
                            }.Index(new BlockFetcher(_Indexer.GetCheckpoint(IndexerCheckpoints.Balances), repo, _Chain)
                            {
                                CancellationToken = cancel.Token
                            }, _Indexer.TaskScheduler);
                        });
                        TryLock(_LockSubscriptions, () =>
                        {
                            using (_SubscriptionSlimLock.LockRead())
                            {
                                new IndexNotificationsTask(Configuration, _Subscriptions)
                                {
                                    EnsureIsSetup = false,
                                }
                                .Index(new BlockFetcher(_Indexer.GetCheckpointRepository().GetCheckpoint("subscriptions"), repo, _Chain)
                                {
                                    CancellationToken = cancel.Token
                                }, _Indexer.TaskScheduler);
                            }
                        });
                        cancel.Dispose();
                        var unused = _Configuration.Topics.NewBlocks.AddAsync(header);
                    });
                }
            }
            if (message.Message.Payload is GetDataPayload)
            {
                var getData = (GetDataPayload)message.Message.Payload;
                foreach (var data in getData.Inventory)
                {
                    Transaction tx = null;
                    if (data.Type == InventoryType.MSG_TX && _Broadcasting.TryGetValue(data.Hash, out tx))
                    {
                        var payload = new TxPayload(tx);
                        node.SendMessageAsync(payload);
                        ListenerTrace.Info("Broadcasted " + data.Hash);
                    }
                }
            }
            if (message.Message.Payload is RejectPayload)
            {
                var     reject = (RejectPayload)message.Message.Payload;
                uint256 txId   = reject.Hash;
                if (txId != null)
                {
                    ListenerTrace.Info("Broadcasted transaction rejected (" + reject.Code + ") " + txId);
                    if (reject.Code != RejectCode.DUPLICATE)
                    {
                        Configuration.GetRejectTable().Create(txId.ToString(), reject);
                    }
                    Transaction tx;
                    _Broadcasting.TryRemove(txId, out tx);
                }
            }
        }
Ejemplo n.º 25
0
        private void ProcessTxPayload(TxPayload transactionPayload)
        {
            var transaction = transactionPayload.Object as Transaction;

            MemPoolService.OnTransactionReceived(new SmartTransaction(transaction, Height.Unknown));
        }