/// <summary> /// Calculates the priority of a transaction based upon transaction size and priority inputs. /// </summary> /// <param name="trx">Memory pool transaction.</param> /// <param name="dPriorityInputs">Priority weighting of inputs.</param> /// <param name="nTxSize">Transaction size, 0 will compute.</param> /// <returns>Priority value.</returns> private double ComputePriority(Transaction trx, double dPriorityInputs, int nTxSize = 0) { nTxSize = MempoolValidator.CalculateModifiedSize(nTxSize, trx, this.mempoolValidator.ConsensusOptions); if (nTxSize == 0) { return(0.0); } return(dPriorityInputs / nTxSize); }
/// <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) { 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.Options.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); } return(true); }
public MempoolBehavior( MempoolValidator validator, MempoolManager manager, MempoolOrphans orphans, IConnectionManager connectionManager, ChainState chainState, Signals.Signals signals, ILoggerFactory loggerFactory) : this(validator, manager, orphans, connectionManager, chainState, signals, loggerFactory.CreateLogger(typeof(MempoolBehavior).FullName)) { }
/// <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 Task <bool> AddOrphanTx(ulong nodeId, Transaction tx) { return(this.MempoolLock.WriteAsync(() => { uint256 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): int sz = MempoolValidator.GetTransactionWeight(tx, this.Validator.ConsensusOptions); if (sz >= this.consensusValidator.ConsensusOptions.MaxStandardTxWeight) { this.mempoolLogger.LogInformation($"ignoring large orphan tx (size: {sz}, hash: {hash})"); return false; } var orphan = new OrphanTx { Tx = tx, NodeId = nodeId, TimeExpire = this.dateTimeProvider.GetTime() + OrphanTxExpireTime }; if (this.mapOrphanTransactions.TryAdd(hash, orphan)) { foreach (var 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.mempoolLogger.LogInformation($"stored orphan tx {hash} (mapsz {orphanSize} outsz {this.mapOrphanTransactionsByPrev.Count})"); this.Validator.PerformanceCounter.SetMempoolOrphanSize(orphanSize); return true; })); }
public MempoolManager( MempoolScheduler mempoolScheduler, TxMempool memPool, MempoolValidator validator, MempoolOrphans orphans, IDateTimeProvider dateTimeProvider, NodeSettings nodeArgs, IMempoolPersistence mempoolPersistence, ILoggerFactory loggerFactory) { this.MempoolScheduler = mempoolScheduler; this.memPool = memPool; this.DateTimeProvider = dateTimeProvider; this.NodeArgs = nodeArgs; this.Orphans = orphans; this.Validator = validator; this.mempoolPersistence = mempoolPersistence; this.mempoolLogger = loggerFactory.CreateLogger(this.GetType().FullName); }
public MempoolBehavior( MempoolValidator validator, MempoolManager manager, MempoolOrphans orphans, IConnectionManager connectionManager, ChainState chainState, Signals.Signals signals, ILogger logger) { this.validator = validator; this.manager = manager; this.orphans = orphans; this.connectionManager = connectionManager; this.chainState = chainState; this.signals = signals; this.logger = logger; this.inventoryTxToSend = new Dictionary <uint256, uint256>(); this.filterInventoryKnown = new Dictionary <uint256, uint256>(); }
/// <summary> /// Constructs a transaction memory pool entry. /// </summary> /// <param name="transaction">Transaction for the entry.</param> /// <param name="nFee">Fee for the transaction in the entry in the memory pool.</param> /// <param name="nTime">The local time when entering the memory pool.</param> /// <param name="entryPriority">Priority when entering the memory pool.</param> /// <param name="entryHeight">The chain height when entering the mempool.</param> /// <param name="inChainInputValue">The sum of all txin values that are already in blockchain.</param> /// <param name="spendsCoinbase">Whether the transaction spends a coinbase.</param> /// <param name="nSigOpsCost">The total signature operations cost.</param> /// <param name="lp">Tthe lock points that track the height and time at which tx was final.</param> /// <param name="consensusOptions">Proof of work consensus options used to compute transaction weight and modified size.</param> public TxMempoolEntry(Transaction transaction, Money nFee, long nTime, double entryPriority, int entryHeight, Money inChainInputValue, bool spendsCoinbase, long nSigOpsCost, LockPoints lp, ConsensusOptions consensusOptions) { this.Transaction = transaction; this.TransactionHash = transaction.GetHash(); this.Fee = nFee; this.Time = nTime; this.entryPriority = entryPriority; this.EntryHeight = entryHeight; this.InChainInputValue = inChainInputValue; this.SpendsCoinbase = spendsCoinbase; this.SigOpCost = nSigOpsCost; this.LockPoints = lp; this.consensusOptions = consensusOptions; this.TxWeight = MempoolValidator.GetTransactionWeight(transaction, consensusOptions); this.nModSize = MempoolValidator.CalculateModifiedSize(this.Transaction.GetSerializedSize(), this.Transaction, consensusOptions); this.nUsageSize = transaction.GetSerializedSize(); // RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(Transaction); this.CountWithDescendants = 1; this.SizeWithDescendants = this.GetTxSize(); this.ModFeesWithDescendants = this.Fee; Money nValueIn = transaction.TotalOut + this.Fee; Guard.Assert(this.InChainInputValue <= nValueIn); this.feeDelta = 0; this.CountWithAncestors = 1; this.SizeWithAncestors = this.GetTxSize(); this.ModFeesWithAncestors = this.Fee; this.SigOpCostWithAncestors = this.SigOpCost; }
public MempoolCoinView(CoinView inner, TxMempool memPool, AsyncLock mempoolScheduler, MempoolValidator mempoolValidator) { this.Inner = inner; this.memPool = memPool; this.mempoolScheduler = mempoolScheduler; this.mempoolValidator = mempoolValidator; this.Set = new UnspentOutputSet(); }