diff options
Diffstat (limited to 'src/policy')
-rw-r--r-- | src/policy/fees.cpp | 54 | ||||
-rw-r--r-- | src/policy/fees.h | 23 | ||||
-rw-r--r-- | src/policy/policy.cpp | 44 | ||||
-rw-r--r-- | src/policy/policy.h | 6 | ||||
-rw-r--r-- | src/policy/rbf.cpp | 46 | ||||
-rw-r--r-- | src/policy/rbf.h | 20 |
6 files changed, 149 insertions, 44 deletions
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index ffe31d1942..de3c060d6a 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -4,6 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "policy/fees.h" +#include "policy/policy.h" #include "amount.h" #include "primitives/transaction.h" @@ -86,7 +87,7 @@ double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal, int maxbucketindex = buckets.size() - 1; // requireGreater means we are looking for the lowest fee/priority such that all higher - // values pass, so we start at maxbucketindex (highest fee) and look at succesively + // values pass, so we start at maxbucketindex (highest fee) and look at successively // smaller buckets until we reach failure. Otherwise, we are looking for the highest // fee/priority such that all lower values fail, and we go in the opposite direction. unsigned int startbucket = requireGreater ? maxbucketindex : 0; @@ -504,6 +505,33 @@ CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget) return CFeeRate(median); } +CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool) +{ + if (answerFoundAtTarget) + *answerFoundAtTarget = confTarget; + // Return failure if trying to analyze a target we're not tracking + if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms()) + return CFeeRate(0); + + double median = -1; + while (median < 0 && (unsigned int)confTarget <= feeStats.GetMaxConfirms()) { + median = feeStats.EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); + } + + if (answerFoundAtTarget) + *answerFoundAtTarget = confTarget - 1; + + // If mempool is limiting txs , return at least the min fee from the mempool + CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); + if (minPoolFee > 0 && minPoolFee > median) + return CFeeRate(minPoolFee); + + if (median < 0) + return CFeeRate(0); + + return CFeeRate(median); +} + double CBlockPolicyEstimator::estimatePriority(int confTarget) { // Return failure if trying to analyze a target we're not tracking @@ -513,6 +541,30 @@ double CBlockPolicyEstimator::estimatePriority(int confTarget) return priStats.EstimateMedianVal(confTarget, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); } +double CBlockPolicyEstimator::estimateSmartPriority(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool) +{ + if (answerFoundAtTarget) + *answerFoundAtTarget = confTarget; + // Return failure if trying to analyze a target we're not tracking + if (confTarget <= 0 || (unsigned int)confTarget > priStats.GetMaxConfirms()) + return -1; + + // If mempool is limiting txs, no priority txs are allowed + CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); + if (minPoolFee > 0) + return INF_PRIORITY; + + double median = -1; + while (median < 0 && (unsigned int)confTarget <= priStats.GetMaxConfirms()) { + median = priStats.EstimateMedianVal(confTarget++, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); + } + + if (answerFoundAtTarget) + *answerFoundAtTarget = confTarget - 1; + + return median; +} + void CBlockPolicyEstimator::Write(CAutoFile& fileout) { fileout << nBestSeenHeight; diff --git a/src/policy/fees.h b/src/policy/fees.h index 15577d128a..3fa31c39e7 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -15,6 +15,7 @@ class CAutoFile; class CFeeRate; class CTxMemPoolEntry; +class CTxMemPool; /** \class CBlockPolicyEstimator * The BlockPolicyEstimator is used for estimating the fee or priority needed @@ -28,7 +29,7 @@ class CTxMemPoolEntry; * included in blocks before transactions of lower fee/priority. So for * example if you wanted to know what fee you should put on a transaction to * be included in a block within the next 5 blocks, you would start by looking - * at the bucket with with the highest fee transactions and verifying that a + * at the bucket with the highest fee transactions and verifying that a * sufficiently high percentage of them were confirmed within 5 blocks and * then you would look at the next highest fee bucket, and so on, stopping at * the last bucket to pass the test. The average fee of transactions in this @@ -86,13 +87,13 @@ private: // Count the total # of txs in each bucket // Track the historical moving average of this total over blocks std::vector<double> txCtAvg; - // and calcuate the total for the current block to update the moving average + // and calculate the total for the current block to update the moving average std::vector<int> curBlockTxCt; // Count the total # of txs confirmed within Y blocks in each bucket // Track the historical moving average of theses totals over blocks std::vector<std::vector<double> > confAvg; // confAvg[Y][X] - // and calcuate the totals for the current block to update the moving averages + // and calculate the totals for the current block to update the moving averages std::vector<std::vector<int> > curBlockConf; // curBlockConf[Y][X] // Sum the total priority/fee of all tx's in each bucket @@ -182,8 +183,8 @@ static const unsigned int MAX_BLOCK_CONFIRMS = 25; /** Decay of .998 is a half-life of 346 blocks or about 2.4 days */ static const double DEFAULT_DECAY = .998; -/** Require greater than 85% of X fee transactions to be confirmed within Y blocks for X to be big enough */ -static const double MIN_SUCCESS_PCT = .85; +/** Require greater than 95% of X fee transactions to be confirmed within Y blocks for X to be big enough */ +static const double MIN_SUCCESS_PCT = .95; static const double UNLIKELY_PCT = .5; /** Require an avg of 1 tx in the combined fee bucket per block to have stat significance */ @@ -242,9 +243,21 @@ public: /** Return a fee estimate */ CFeeRate estimateFee(int confTarget); + /** Estimate fee rate needed to get be included in a block within + * confTarget blocks. If no answer can be given at confTarget, return an + * estimate at the lowest target where one can be given. + */ + CFeeRate estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool); + /** Return a priority estimate */ double estimatePriority(int confTarget); + /** Estimate priority needed to get be included in a block within + * confTarget blocks. If no answer can be given at confTarget, return an + * estimate at the lowest target where one can be given. + */ + double estimateSmartPriority(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool); + /** Write estimation data to a file */ void Write(CAutoFile& fileout); diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 4c96fbf5a5..332abc430e 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers +// Copyright (c) 2009-2015 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,9 +23,6 @@ * 2. P2SH scripts with a crazy number of expensive * CHECKSIG/CHECKMULTISIG operations * - * Check transaction inputs, and make sure any - * pay-to-script-hash transactions are evaluating IsStandard scripts - * * Why bother? To avoid denial-of-service attacks; an attacker * can submit a standard HASH... OP_EQUAL transaction, * which will get accepted into blocks. The redemption @@ -50,7 +47,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) if (m < 1 || m > n) return false; } else if (whichType == TX_NULL_DATA && - (!GetBoolArg("-datacarrier", true) || scriptPubKey.size() > nMaxDatacarrierBytes)) + (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) return false; return whichType != TX_NONSTANDARD; @@ -135,45 +132,20 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) const CScript& prevScript = prev.scriptPubKey; if (!Solver(prevScript, whichType, vSolutions)) return false; - int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions); - if (nArgsExpected < 0) - return false; - - // Transactions with extra stuff in their scriptSigs are - // non-standard. Note that this EvalScript() call will - // be quick, because if there are any operations - // beside "push data" in the scriptSig - // IsStandardTx() will have already returned false - // and this method isn't called. - std::vector<std::vector<unsigned char> > stack; - if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker())) - return false; if (whichType == TX_SCRIPTHASH) { + std::vector<std::vector<unsigned char> > stack; + // convert the scriptSig into a stack, so we can inspect the redeemScript + if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0)) + return false; if (stack.empty()) return false; CScript subscript(stack.back().begin(), stack.back().end()); - std::vector<std::vector<unsigned char> > vSolutions2; - txnouttype whichType2; - if (Solver(subscript, whichType2, vSolutions2)) - { - int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); - if (tmpExpected < 0) - return false; - nArgsExpected += tmpExpected; - } - else - { - // Any other Script with less than 15 sigops OK: - unsigned int sigops = subscript.GetSigOpCount(true); - // ... extra data left on the stack after execution is OK, too: - return (sigops <= MAX_P2SH_SIGOPS); + if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) { + return false; } } - - if (stack.size() != (unsigned int)nArgsExpected) - return false; } return true; diff --git a/src/policy/policy.h b/src/policy/policy.h index f269e8d476..726864f190 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers +// Copyright (c) 2009-2015 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -18,13 +18,15 @@ class CCoinsViewCache; static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ -static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; +static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0; /** The maximum size for transactions we're willing to relay/mine */ static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; +/** Default for -maxmempool, maximum megabytes of mempool memory usage */ +static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300; /** * Standard script verification flags that standard transactions will comply * with. However scripts violating these flags may still be present in valid diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp new file mode 100644 index 0000000000..98b1a1ba4c --- /dev/null +++ b/src/policy/rbf.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2016 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "policy/rbf.h" + +bool SignalsOptInRBF(const CTransaction &tx) +{ + BOOST_FOREACH(const CTxIn &txin, tx.vin) { + if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1) { + return true; + } + } + return false; +} + +bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool) +{ + AssertLockHeld(pool.cs); + + CTxMemPool::setEntries setAncestors; + + // First check the transaction itself. + if (SignalsOptInRBF(entry.GetTx())) { + return true; + } + + // If this transaction is not in our mempool, then we can't be sure + // we will know about all its inputs. + if (!pool.exists(entry.GetTx().GetHash())) { + throw std::runtime_error("Cannot determine RBF opt-in signal for non-mempool transaction\n"); + } + + // If all the inputs have nSequence >= maxint-1, it still might be + // signaled for RBF if any unconfirmed parents have signaled. + uint64_t noLimit = std::numeric_limits<uint64_t>::max(); + std::string dummy; + pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false); + + BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) { + if (SignalsOptInRBF(it->GetTx())) { + return true; + } + } + return false; +} diff --git a/src/policy/rbf.h b/src/policy/rbf.h new file mode 100644 index 0000000000..925ce0d9bd --- /dev/null +++ b/src/policy/rbf.h @@ -0,0 +1,20 @@ +// Copyright (c) 2016 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_POLICY_RBF_H +#define BITCOIN_POLICY_RBF_H + +#include "txmempool.h" + +// Check whether the sequence numbers on this transaction are signaling +// opt-in to replace-by-fee, according to BIP 125 +bool SignalsOptInRBF(const CTransaction &tx); + +// Determine whether an in-mempool transaction is signaling opt-in to RBF +// according to BIP 125 +// This involves checking sequence numbers of the transaction, as well +// as the sequence numbers of all in-mempool ancestors. +bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool); + +#endif // BITCOIN_POLICY_RBF_H |