示例#1
0
        public TxMempoolEntry(Transaction transaction, Money nFee,
                              long nTime, double entryPriority, int entryHeight,
                              Money inChainInputValue, bool spendsCoinbase,
                              long nSigOpsCost, LockPoints lp)
        {
            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.TxWeight = MempoolValidator.GetTransactionWeight(transaction);
            nModSize      = MempoolValidator.CalculateModifiedSize(this.Transaction.GetSerializedSize(), this.Transaction);

            nUsageSize = transaction.GetSerializedSize();             // RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(Transaction);

            CountWithDescendants   = 1;
            SizeWithDescendants    = GetTxSize();
            ModFeesWithDescendants = Fee;
            Money nValueIn = transaction.TotalOut + Fee;

            Guard.Assert(InChainInputValue <= nValueIn);

            feeDelta = 0;

            CountWithAncestors     = 1;
            SizeWithAncestors      = GetTxSize();
            ModFeesWithAncestors   = Fee;
            SigOpCostWithAncestors = SigOpCost;
        }
        // Check if transaction will be BIP 68 final in the next block to be created.
        // Simulates calling SequenceLocks() with data from the tip of the current active chain.
        // Optionally stores in LockPoints the resulting height and time calculated and the hash
        // of the block needed for calculation or skips the calculation and uses the LockPoints
        // passed in for evaluation.
        // The LockPoints should not be considered valid if CheckSequenceLocks returns false.
        // See consensus/consensus.h for flag definitions.
        public static bool CheckSequenceLocks(ChainedBlock tip, MempoolValidationContext context, Transaction.LockTimeFlags flags, LockPoints lp = null,
                                              bool useExistingLockPoints = false)
        {
            var dummyBlock = new Block {
                Header = { HashPrevBlock = tip.HashBlock }
            };
            ChainedBlock index = new ChainedBlock(dummyBlock.Header, dummyBlock.GetHash(), tip);

            // CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
            // height based locks because when SequenceLocks() is called within
            // ConnectBlock(), the height of the block *being*
            // evaluated is what is used.
            // Thus if we want to know if a transaction can be part of the
            // *next* block, we need to use one more than chainActive.Height()

            SequenceLock lockPair;

            if (useExistingLockPoints)
            {
                Guard.Assert(lp != null);
                lockPair = new SequenceLock(lp.Height, lp.Time);
            }
            else
            {
                // pcoinsTip contains the UTXO set for chainActive.Tip()
                List <int> prevheights = new List <int>();
                foreach (var txin in context.Transaction.Inputs)
                {
                    var coins = context.View.GetCoins(txin.PrevOut.Hash);
                    if (coins == null)
                    {
                        return(false);
                    }

                    if (coins.Height == TxMempool.MempoolHeight)
                    {
                        // Assume all mempool transaction confirm in the next block
                        prevheights.Add(tip.Height + 1);
                    }
                    else
                    {
                        prevheights.Add((int)coins.Height);
                    }
                }
                lockPair = context.Transaction.CalculateSequenceLocks(prevheights.ToArray(), index, flags);

                if (lp != null)
                {
                    lp.Height = lockPair.MinHeight;
                    lp.Time   = lockPair.MinTime.ToUnixTimeMilliseconds();
                    // Also store the hash of the block with the highest height of
                    // all the blocks which have sequence locked prevouts.
                    // This hash needs to still be on the chain
                    // for these LockPoint calculations to be valid
                    // Note: It is impossible to correctly calculate a maxInputBlock
                    // if any of the sequence locked inputs depend on unconfirmed txs,
                    // except in the special case where the relative lock time/height
                    // is 0, which is equivalent to no sequence lock. Since we assume
                    // input height of tip+1 for mempool txs and test the resulting
                    // lockPair from CalculateSequenceLocks against tip+1.  We know
                    // EvaluateSequenceLocks will fail if there was a non-zero sequence
                    // lock on a mempool input, so we can use the return value of
                    // CheckSequenceLocks to indicate the LockPoints validity
                    int maxInputHeight = 0;
                    foreach (var height in prevheights)
                    {
                        // Can ignore mempool inputs since we'll fail if they had non-zero locks
                        if (height != tip.Height + 1)
                        {
                            maxInputHeight = Math.Max(maxInputHeight, height);
                        }
                    }

                    lp.MaxInputBlock = tip.GetAncestor(maxInputHeight);
                }
            }

            return(lockPair.Evaluate(index));
        }
示例#3
0
 // Update the LockPoints after a reorg
 public void UpdateLockPoints(LockPoints lp)
 {
     this.LockPoints = lp;
 }