Пример #1
0
 /// <summary>
 /// Constructs a memory pool feature.
 /// </summary>
 /// <param name="connectionManager">Connection manager for managing node connections.</param>
 /// <param name="signals">Node notifications available to subscribe to.</param>
 /// <param name="mempoolSignaled">Observes block signal notifications from signals.</param>
 /// <param name="mempoolBehavior">Memory pool node behavior for managing attached node messages.</param>
 /// <param name="mempoolManager">Memory pool manager for managing external access to memory pool.</param>
 /// <param name="nodeSettings">User defined node settings.</param>
 /// <param name="loggerFactory">Logger factory for creating instance logger.</param>
 /// <param name="mempoolSettings">Mempool settings.</param>
 public MempoolFeature(
     IConnectionManager connectionManager,
     Signals.Signals signals,
     MempoolSignaled mempoolSignaled,
     MempoolBehavior mempoolBehavior,
     MempoolManager mempoolManager,
     NodeSettings nodeSettings,
     ILoggerFactory loggerFactory,
     MempoolSettings mempoolSettings)
 {
     this.signals           = signals;
     this.connectionManager = connectionManager;
     this.mempoolSignaled   = mempoolSignaled;
     this.mempoolBehavior   = mempoolBehavior;
     this.mempoolManager    = mempoolManager;
     this.mempoolLogger     = loggerFactory.CreateLogger(this.GetType().FullName);
     this.mempoolSettings   = mempoolSettings;
     this.nodeSettings      = nodeSettings;
 }
Пример #2
0
        /// <summary>
        /// Processes orphan transactions.
        /// Executed when receive a new transaction through MempoolBehavior.
        /// </summary>
        /// <param name="behavior">Memory pool behavior that received new transaction.</param>
        /// <param name="tx">The new transaction received.</param>
        public async Task ProcessesOrphansAsync(MempoolBehavior behavior, Transaction tx)
        {
            Queue <OutPoint> vWorkQueue  = new Queue <OutPoint>();
            List <uint256>   vEraseQueue = new List <uint256>();

            uint256 trxHash = tx.GetHash();

            for (int index = 0; index < tx.Outputs.Count; index++)
            {
                vWorkQueue.Enqueue(new OutPoint(trxHash, index));
            }

            // Recursively process any orphan transactions that depended on this one
            List <ulong> setMisbehaving = new List <ulong>();

            while (vWorkQueue.Any())
            {
                // mapOrphanTransactionsByPrev.TryGet() does a .ToList() to take a new collection
                // of orphans as this collection may be modifed later by anotehr thread
                List <OrphanTx> itByPrev = await this.MempoolLock.ReadAsync(() => this.mapOrphanTransactionsByPrev.TryGet(vWorkQueue.Dequeue())?.ToList());

                if (itByPrev == null)
                {
                    continue;
                }

                foreach (OrphanTx mi in itByPrev)
                {
                    Transaction orphanTx   = mi.Tx;     //->second.tx;
                    uint256     orphanHash = orphanTx.GetHash();
                    ulong       fromPeer   = mi.NodeId; // (*mi)->second.fromPeer;

                    if (setMisbehaving.Contains(fromPeer))
                    {
                        continue;
                    }

                    // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
                    // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
                    // anyone relaying LegitTxX banned)
                    MempoolValidationState stateDummy = new MempoolValidationState(true);
                    if (await this.Validator.AcceptToMemoryPool(stateDummy, orphanTx))
                    {
                        this.mempoolLogger.LogInformation($"accepted orphan tx {orphanHash}");
                        await behavior.RelayTransaction(orphanTx.GetHash());

                        this.signals.SignalTransaction(orphanTx);
                        for (int index = 0; index < orphanTx.Outputs.Count; index++)
                        {
                            vWorkQueue.Enqueue(new OutPoint(orphanHash, index));
                        }
                        vEraseQueue.Add(orphanHash);
                    }
                    else if (!stateDummy.MissingInputs)
                    {
                        int nDos = 0;
                        if (stateDummy.IsInvalid && nDos > 0)
                        {
                            // Punish peer that gave us an invalid orphan tx
                            //Misbehaving(fromPeer, nDos);
                            setMisbehaving.Add(fromPeer);
                            this.mempoolLogger.LogInformation($"invalid orphan tx {orphanHash}");
                        }
                        // Has inputs but not accepted to mempool
                        // Probably non-standard or insufficient fee/priority
                        this.mempoolLogger.LogInformation($"removed orphan tx {orphanHash}");
                        vEraseQueue.Add(orphanHash);
                        if (!orphanTx.HasWitness && !stateDummy.CorruptionPossible)
                        {
                            // 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.
                            await this.MempoolLock.WriteAsync(() => this.recentRejects.TryAdd(orphanHash, orphanHash));
                        }
                    }
                    this.memPool.Check(new MempoolCoinView(this.coinView, this.memPool, this.MempoolLock, this.Validator));
                }
            }

            foreach (uint256 hash in vEraseQueue)
            {
                await this.EraseOrphanTx(hash).ConfigureAwait(false);
            }
        }