コード例 #1
0
 /// <summary>
 ///     Checks that are done before touching the memory pool.
 ///     These checks don't need to run under the memory pool lock.
 /// </summary>
 /// <param name="context">Current validation context.</param>
 protected virtual void PreMempoolChecks(MempoolValidationContext context)
 {
     // TODO: fix this to use dedicated mempool rules.
     new CheckPowTransactionRule {
         Logger = this.logger
     }.CheckTransaction(this.network,
                        this.network.Consensus.Options, context.Transaction);
     if (this.chainIndexer.Network.Consensus.IsProofOfStake)
     {
         new CheckPosTransactionRule {
             Logger = this.logger
         }
     }
コード例 #2
0
        /// <summary>
        ///     Validates and then adds a transaction to memory pool.
        /// </summary>
        /// <param name="state">Validation state for creating the validation context.</param>
        /// <param name="tx">The transaction to validate.</param>
        /// <param name="vHashTxnToUncache">Not currently used</param>
        async Task AcceptToMemoryPoolWorkerAsync(MempoolValidationState state, Transaction tx,
                                                 List <uint256> vHashTxnToUncache)
        {
            var context = new MempoolValidationContext(tx, state);

            context.MinRelayTxFee = this.minRelayTxFee;

            // TODO: Convert these into rules too
            PreMempoolChecks(context);

            // Create the MemPoolCoinView and load relevant utxoset
            context.View = new MempoolCoinView(this.coinView, this.memPool, this.mempoolLock, this);

            // adding to the mem pool can only be done sequentially
            // use the sequential scheduler for that.
            await this.mempoolLock.WriteAsync(() =>
            {
                context.View.LoadViewLocked(context.Transaction);

                // If the transaction already exists in the mempool,
                // we only record the state but do not throw an exception.
                // This is because the caller will check if the state is invalid
                // and if so return false, meaning that the transaction should not be relayed.
                if (this.memPool.Exists(context.TransactionHash))
                {
                    state.Invalid(MempoolErrors.InPool);
                    this.logger.LogTrace("(-)[INVALID_TX_ALREADY_EXISTS]");
                    return;
                }

                foreach (var rule in this.mempoolRules)
                {
                    rule.CheckTransaction(context);
                }

                // Remove conflicting transactions from the mempool
                foreach (var it in context.AllConflicting)
                {
                    this.logger.LogInformation(
                        $"Replacing tx {it.TransactionHash} with {context.TransactionHash} for {context.ModifiedFees - context.ConflictingFees} BTC additional fees, {context.EntrySize - context.ConflictingSize} delta bytes");
                }

                this.memPool.RemoveStaged(context.AllConflicting, false);

                // This transaction should only count for fee estimation if
                // the node is not behind and it is not dependent on any other
                // transactions in the mempool
                var validForFeeEstimation = IsCurrentForFeeEstimation() && this.memPool.HasNoInputsOf(tx);

                // Store transaction in memory
                this.memPool.AddUnchecked(context.TransactionHash, context.Entry, context.SetAncestors,
                                          validForFeeEstimation);

                // trim mempool and check if tx was trimmed
                if (!state.OverrideMempoolLimit)
                {
                    LimitMempoolSize(this.mempoolSettings.MaxMempool * 1000000,
                                     this.mempoolSettings.MempoolExpiry * 60 * 60);

                    if (!this.memPool.Exists(context.TransactionHash))
                    {
                        this.logger.LogTrace("(-)[FAIL_MEMPOOL_FULL]");
                        state.Fail(MempoolErrors.Full).Throw();
                    }
                }

                // do this here inside the exclusive scheduler for better accuracy
                // and to avoid springing more concurrent tasks later
                state.MempoolSize        = this.memPool.Size;
                state.MempoolDynamicSize = this.memPool.DynamicMemoryUsage();

                this.PerformanceCounter.SetMempoolSize(state.MempoolSize);
                this.PerformanceCounter.SetMempoolDynamicSize(state.MempoolDynamicSize);
                this.PerformanceCounter.AddHitCount(1);
            });
        }
コード例 #3
0
 /// <inheritdoc />
 public abstract void CheckTransaction(MempoolValidationContext context);