public MempoolFeature(ConnectionManager connectionManager, Signals signals, MempoolSignaled mempoolSignaled, MempoolBehavior mempoolBehavior) { this.signals = signals; this.connectionManager = connectionManager; this.mempoolSignaled = mempoolSignaled; this.mempoolBehavior = mempoolBehavior; }
public async Task ProcessesOrphans(MempoolBehavior behavior, Transaction tx) { Queue <OutPoint> vWorkQueue = new Queue <OutPoint>(); List <uint256> vEraseQueue = new List <uint256>(); var trxHash = tx.GetHash(); for (var 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 var itByPrev = await this.MempoolScheduler.ReadAsync(() => this.mapOrphanTransactionsByPrev.TryGet(vWorkQueue.Dequeue())?.ToList()); if (itByPrev == null) { continue; } foreach (var mi in itByPrev) { var orphanTx = mi.Tx; //->second.tx; var orphanHash = orphanTx.GetHash(); var 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)) { Logging.Logs.Mempool.LogInformation($"accepted orphan tx {orphanHash}"); await behavior.RelayTransaction(orphanTx.GetHash()); for (var 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); Logging.Logs.Mempool.LogInformation($"invalid orphan tx {orphanHash}"); } // Has inputs but not accepted to mempool // Probably non-standard or insufficient fee/priority Logging.Logs.Mempool.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.MempoolScheduler.WriteAsync(() => this.recentRejects.TryAdd(orphanHash, orphanHash)); } } this.memPool.Check(new MempoolCoinView(this.coinView, this.memPool, this.MempoolScheduler, this.Validator)); } } foreach (var hash in vEraseQueue) { await this.EraseOrphanTx(hash); } }