Пример #1
0
        /// <summary>
        /// Erase an specific transaction from orphan pool.
        /// </summary>
        /// <param name="hash">hash of the transaction.</param>
        /// <returns>Whether erased.</returns>
        private bool EraseOrphanTxLock(uint256 hash)
        {
            OrphanTx orphTx = this.mapOrphanTransactions.TryGet(hash);

            if (orphTx == null)
            {
                this.logger.LogTrace("(-)[NOTFOUND_ORPH]:false");
                return(false);
            }

            foreach (TxIn txin in orphTx.Tx.Inputs)
            {
                List <OrphanTx> prevOrphTxList = this.mapOrphanTransactionsByPrev.TryGet(txin.PrevOut);

                if (prevOrphTxList == null)
                {
                    continue;
                }

                prevOrphTxList.Remove(orphTx);

                if (!prevOrphTxList.Any())
                {
                    this.mapOrphanTransactionsByPrev.Remove(txin.PrevOut);
                }
            }

            this.mapOrphanTransactions.Remove(hash);

            int orphanSize = this.mapOrphanTransactions.Count;

            this.Validator.PerformanceCounter.SetMempoolOrphanSize(orphanSize);

            return(true);
        }
Пример #2
0
 /// <summary>
 /// Erase an specific transaction from orphan pool.
 /// </summary>
 /// <param name="hash">hash of the transaction.</param>
 /// <returns>Whether erased.</returns>
 private Task <bool> EraseOrphanTx(uint256 hash)
 {
     return(this.MempoolLock.WriteAsync(() =>
     {
         OrphanTx it = this.mapOrphanTransactions.TryGet(hash);
         if (it == null)
         {
             return false;
         }
         foreach (TxIn txin in it.Tx.Inputs)
         {
             List <OrphanTx> itPrev = this.mapOrphanTransactionsByPrev.TryGet(txin.PrevOut);
             if (itPrev == null)
             {
                 continue;
             }
             itPrev.Remove(it);
             if (!itPrev.Any())
             {
                 this.mapOrphanTransactionsByPrev.Remove(txin.PrevOut);
             }
         }
         this.mapOrphanTransactions.Remove(hash);
         return true;
     }));
 }
        /// <summary>
        /// Add an orphan transaction to the orphan pool.
        /// </summary>
        /// <param name="nodeId">Node id of the source node.</param>
        /// <param name="tx">The transaction to add.</param>
        /// <returns>Whether the orphan transaction was added.</returns>
        public bool AddOrphanTx(ulong nodeId, Transaction tx)
        {
            this.logger.LogTrace("({0}:{1},{2}:'{3}')", nameof(nodeId), nodeId, nameof(tx), tx.GetHash());

            lock (this.lockObject)
            {
                uint256 hash = tx.GetHash();
                if (this.mapOrphanTransactions.ContainsKey(hash))
                {
                    this.logger.LogTrace("(-)[DUP_ORPH]:false");
                    return(false);
                }

                // Ignore big transactions, to avoid a
                // send-big-orphans memory exhaustion attack. If a peer has a legitimate
                // large transaction with a missing parent then we assume
                // it will rebroadcast it later, after the parent transaction(s)
                // have been mined or received.
                // 100 orphans, each of which is at most 99,999 bytes big is
                // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
                int sz = MempoolValidator.GetTransactionWeight(tx, this.Validator.ConsensusOptions);
                if (sz >= this.chain.Network.Consensus.Option <PowConsensusOptions>().MaxStandardTxWeight)
                {
                    this.logger.LogInformation("ignoring large orphan tx (size: {0}, hash: {1})", sz, hash);
                    this.logger.LogTrace("(-)[LARGE_ORPH]:false");
                    return(false);
                }

                var orphan = new OrphanTx
                {
                    Tx         = tx,
                    NodeId     = nodeId,
                    TimeExpire = this.dateTimeProvider.GetTime() + OrphanTxExpireTime
                };

                if (this.mapOrphanTransactions.TryAdd(hash, orphan))
                {
                    foreach (TxIn txin in tx.Inputs)
                    {
                        List <OrphanTx> prv = this.mapOrphanTransactionsByPrev.TryGet(txin.PrevOut);
                        if (prv == null)
                        {
                            prv = new List <OrphanTx>();
                            this.mapOrphanTransactionsByPrev.Add(txin.PrevOut, prv);
                        }
                        prv.Add(orphan);
                    }
                }

                int orphanSize = this.mapOrphanTransactions.Count;
                this.logger.LogInformation("stored orphan tx {0} (mapsz {1} outsz {2})", hash, orphanSize, this.mapOrphanTransactionsByPrev.Count);
                this.Validator.PerformanceCounter.SetMempoolOrphanSize(orphanSize);
            }

            this.logger.LogTrace("(-):true");
            return(true);
        }
        public Task <bool> AddOrphanTx(ulong nodeId, Transaction tx)
        {
            return(this.MempoolScheduler.WriteAsync(() =>
            {
                var hash = tx.GetHash();
                if (this.mapOrphanTransactions.ContainsKey(hash))
                {
                    return false;
                }

                // Ignore big transactions, to avoid a
                // send-big-orphans memory exhaustion attack. If a peer has a legitimate
                // large transaction with a missing parent then we assume
                // it will rebroadcast it later, after the parent transaction(s)
                // have been mined or received.
                // 100 orphans, each of which is at most 99,999 bytes big is
                // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
                var sz = MempoolValidator.GetTransactionWeight(tx, this.Validator.ConsensusOptions);
                if (sz >= this.consensusValidator.ConsensusOptions.MAX_STANDARD_TX_WEIGHT)
                {
                    Logging.Logs.Mempool.LogInformation($"ignoring large orphan tx (size: {sz}, hash: {hash})");
                    return false;
                }

                var orphan = new OrphanTx
                {
                    Tx = tx,
                    NodeId = nodeId,
                    TimeExpire = this.dateTimeProvider.GetTime() + ORPHAN_TX_EXPIRE_TIME
                };
                if (this.mapOrphanTransactions.TryAdd(hash, orphan))
                {
                    foreach (var txin in tx.Inputs)
                    {
                        var prv = this.mapOrphanTransactionsByPrev.TryGet(txin.PrevOut);
                        if (prv == null)
                        {
                            prv = new List <OrphanTx>();
                            this.mapOrphanTransactionsByPrev.Add(txin.PrevOut, prv);
                        }
                        prv.Add(orphan);
                    }
                }

                var orphanSize = this.mapOrphanTransactions.Count;
                Logging.Logs.Mempool.LogInformation(
                    $"stored orphan tx {hash} (mapsz {orphanSize} outsz {this.mapOrphanTransactionsByPrev.Count})");
                this.Validator.PerformanceCounter.SetMempoolOrphanSize(orphanSize);

                return true;
            }));
        }