private void UpdateChild(TxMempoolEntry entry, TxMempoolEntry child, bool add)
 {
     // todo: find how to take a memory size of SetEntries
     //setEntries s;
     if (add && this.mapLinks[entry].Children.Add(child))
     {
         this.cachedInnerUsage += child.DynamicMemoryUsage();
     }
     else if (!add && this.mapLinks[entry].Children.Remove(child))
     {
         this.cachedInnerUsage -= child.DynamicMemoryUsage();
     }
 }
 private void UpdateParent(TxMempoolEntry entry, TxMempoolEntry parent, bool add)
 {
     // todo: find how to take a memory size of SetEntries
     //SetEntries s;
     if (add && this.mapLinks[entry].Parents.Add(parent))
     {
         this.cachedInnerUsage += parent.DynamicMemoryUsage();
     }
     else if (!add && this.mapLinks[entry].Parents.Remove(parent))
     {
         this.cachedInnerUsage -= parent.DynamicMemoryUsage();
     }
 }
        /** Before calling removeUnchecked for a given transaction,
         *  UpdateForRemoveFromMempool must be called on the entire (dependent) set
         *  of transactions being removed at the same time.  We use each
         *  CTxMemPoolEntry's setMemPoolParents in order to walk ancestors of a
         *  given transaction that is removed, so we can't remove intermediate
         *  transactions in a chain before we've updated all the state for the
         *  removal.
         */
        private void RemoveUnchecked(TxMempoolEntry it)
        {
            var hash = it.TransactionHash;

            foreach (var txin in it.Transaction.Inputs)
            {
                this.MapNextTx.Remove(this.MapNextTx.FirstOrDefault(w => w.OutPoint == txin.PrevOut));
            }

            if (this.vTxHashes.Any())
            {
                this.vTxHashes.Remove(it);

                //vTxHashes[it] = std::move(vTxHashes.back());
                //vTxHashes[it].second->vTxHashesIdx = it->vTxHashesIdx;
                //vTxHashes.pop_back();
                //if (vTxHashes.size() * 2 < vTxHashes.capacity())
                //	vTxHashes.shrink_to_fit();
            }
            //else
            //	vTxHashes.clear();

            this.totalTxSize      -= it.GetTxSize();
            this.cachedInnerUsage -= it.DynamicMemoryUsage();
            this.cachedInnerUsage -= this.mapLinks[it]?.Parents?.Sum(p => p.DynamicMemoryUsage()) ?? 0 + this.mapLinks[it]?.Children?.Sum(p => p.DynamicMemoryUsage()) ?? 0;
            this.mapLinks.Remove(it);
            this.MapTx.Remove(it);
            this.nTransactionsUpdated++;
            this.MinerPolicyEstimator.RemoveTx(hash);
        }
        public bool AddUnchecked(uint256 hash, TxMempoolEntry entry, SetEntries setAncestors, bool validFeeEstimate = true)
        {
            // Add to memory pool without checking anything.
            // Used by main.cpp AcceptToMemoryPool(), which DOES do
            // all the appropriate checks.
            //LOCK(cs);
            this.MapTx.Add(entry);
            this.mapLinks.Add(entry, new TxLinks {
                Parents = new SetEntries(), Children = new SetEntries()
            });

            // Update transaction for any feeDelta created by PrioritiseTransaction
            // TODO: refactor so that the fee delta is calculated before inserting
            // into mapTx.
            var pos = this.mapDeltas.TryGet(hash);

            if (pos != null)
            {
                if (pos.Amount != null)
                {
                    entry.UpdateFeeDelta(pos.Amount.Satoshi);
                }
            }

            // Update cachedInnerUsage to include contained transaction's usage.
            // (When we update the entry for in-mempool parents, memory usage will be
            // further updated.)
            this.cachedInnerUsage += entry.DynamicMemoryUsage();

            var tx = entry.Transaction;
            HashSet <uint256> setParentTransactions = new HashSet <uint256>();

            foreach (var txInput in tx.Inputs)
            {
                this.MapNextTx.Add(new NextTxPair {
                    OutPoint = txInput.PrevOut, Transaction = tx
                });
                setParentTransactions.Add(txInput.PrevOut.Hash);
            }
            // Don't bother worrying about child transactions of this one.
            // Normal case of a new transaction arriving is that there can't be any
            // children, because such children would be orphans.
            // An exception to that is if a transaction enters that used to be in a block.
            // In that case, our disconnect block logic will call UpdateTransactionsFromBlock
            // to clean up the mess we're leaving here.

            // Update ancestors with information about this tx
            foreach (var phash in setParentTransactions)
            {
                var pit = this.MapTx.TryGet(phash);
                if (pit != null)
                {
                    this.UpdateParent(entry, pit, true);
                }
            }

            this.UpdateAncestorsOf(true, entry, setAncestors);
            this.UpdateEntryForAncestors(entry, setAncestors);

            this.nTransactionsUpdated++;
            this.totalTxSize += entry.GetTxSize();

            this.MinerPolicyEstimator.ProcessTransaction(entry, validFeeEstimate);

            this.vTxHashes.Add(entry, tx.GetWitHash());
            //entry.vTxHashesIdx = vTxHashes.size() - 1;

            return(true);
        }