[mining] Remove -blockprioritysize.

Remove ability of mining code to fill part of a block with transactions sorted by coin age.

(cherry picked from commit bitcoin/bitcoin@272b25a6a9)

Zcash:
* Add release notes.
* Remove a static assertion that no longer applies.
* Spell "prioritise" and "prioritisation" (when referring to tx prioritisation) consistently
  with 'ise', to match the "prioritisetransaction" RPC call.

Signed-off-by: Daira Emma Hopwood <daira@jacaranda.org>
This commit is contained in:
Alex Morcos 2017-01-19 13:58:42 -05:00 committed by Daira Emma Hopwood
parent 9231eed603
commit dbf52938af
9 changed files with 20 additions and 113 deletions

View File

@ -39,6 +39,14 @@ Changes to Transaction Fee Selection
`sendmany`, and `fundrawtransaction`) to use a zero fee for "small" transactions
that spend "old" inputs. It will now cause a warning on node startup if used.
Changes to Block Template Construction
--------------------------------------
- The block template construction algorithm no longer favours transactions that
were previously considered "high priority" because they spent older inputs. The
`-blockprioritysize` config option, which configured the portion of the block
reserved for these transactions, has been removed and is now ignored.
Removal of Priority Estimation
------------------------------

View File

@ -27,7 +27,6 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
self.nodes = []
# Start nodes with tiny block size of 11kb
args = [
"-blockprioritysize=7000",
"-blockmaxsize=11000",
"-maxorphantx=1000",
"-relaypriority=true",
@ -42,8 +41,6 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
self.sync_all()
def run_test (self):
# tx priority is calculated: priority = sum(input_value_in_base_units * input_age)/size_in_bytes
print("Mining 11kb blocks...")
self.nodes[0].generate(501)
@ -60,8 +57,8 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
# could take up to 128s. So use a higher timeout on the mempool sync.
sync_mempools(self.nodes, timeout=200)
# Create tx of lower value to be prioritized on node 0
# Older transactions get mined first, so this lower value, newer tx is unlikely to be mined without prioritisation
# Create tx to be prioritised on node 0
# This tx will not be mined without prioritisation.
priority_tx_0 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
# Check that priority_tx_0 is not in block_template() prior to prioritisation
@ -76,7 +73,7 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
priority_success = self.nodes[0].prioritisetransaction(priority_tx_0, 1000, int(3 * base_fee * COIN))
assert(priority_success)
# Check that prioritized transaction is not in getblocktemplate()
# Check that prioritised transaction is not in getblocktemplate()
# (not updated because no new txns)
in_block_template = False
block_template = self.nodes[0].getblocktemplate()
@ -89,7 +86,7 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
# Sending a new transaction will make getblocktemplate refresh within 10s
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
# Check that prioritized transaction is not in getblocktemplate()
# Check that prioritised transaction is not in getblocktemplate()
# (too soon)
in_block_template = False
block_template = self.nodes[0].getblocktemplate()
@ -99,7 +96,7 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
break
assert_equal(in_block_template, False)
# Check that prioritized transaction is in getblocktemplate()
# Check that prioritised transaction is in getblocktemplate()
# getblocktemplate() will refresh after 1 min, or after 10 sec if new transaction is added to mempool
# Mempool is probed every 10 seconds. We'll give getblocktemplate() a maximum of 30 seconds to refresh
block_template = self.nodes[0].getblocktemplate()
@ -117,7 +114,7 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
assert(in_block_template)
# Node 1 doesn't get the next block, so this *shouldn't* be mined despite being prioritized on node 1
# Node 1 doesn't get the next block, so this *shouldn't* be mined despite being prioritised on node 1
priority_tx_1 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 0.1)
self.nodes[1].prioritisetransaction(priority_tx_1, 1000, int(3 * base_fee * COIN))

View File

@ -408,10 +408,6 @@ Block creation options:
-blockmaxsize=<n>
Set maximum block size in bytes (default: 2000000)
-blockprioritysize=<n>
Set maximum size of high-priority/low-fee transactions in bytes
(default: 1000000)
Mining options:
-gen

View File

@ -193,13 +193,12 @@ class EstimateFeeTest(BitcoinTestFramework):
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
# (17k is room enough for 110 or so transactions)
self.nodes.append(start_node(1, self.options.tmpdir,
["-blockprioritysize=1500", "-blockmaxsize=18000",
"-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"]))
["-blockmaxsize=18000", "-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"]))
connect_nodes(self.nodes[1], 0)
# Node2 is a stingy miner, that
# produces too small blocks (room for only 70 or so transactions)
node2args = ["-blockprioritysize=0", "-blockmaxsize=12000", "-maxorphantx=1000", "-relaypriority=0"]
node2args = ["-blockmaxsize=12000", "-maxorphantx=1000", "-relaypriority=0"]
self.nodes.append(start_node(2, self.options.tmpdir, node2args))
connect_nodes(self.nodes[0], 2)

View File

@ -504,7 +504,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Block creation options:"));
strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE));
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
if (GetBoolArg("-help-debug", false))
strUsage += HelpMessageOpt("-blockversion=<n>", strprintf("Override block version to test forking scenarios (default: %d)", (int)CBlock::CURRENT_VERSION));

View File

@ -57,8 +57,8 @@ using namespace std;
//
// Unconfirmed transactions in the memory pool often depend on other
// transactions in the memory pool. When we select transactions from the
// pool, we select by highest priority or fee rate, so we might consider
// transactions that depend on transactions that aren't yet in the block.
// pool, we select by highest fee rate, so we might consider transactions
// that depend on transactions that aren't yet in the block.
std::optional<uint64_t> last_block_num_txs;
std::optional<uint64_t> last_block_size;
@ -437,7 +437,6 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(
}
}
addPriorityTxs();
addScoreTxs();
last_block_num_txs = nBlockTx;
@ -704,80 +703,6 @@ void BlockAssembler::addScoreTxs()
}
}
void BlockAssembler::addPriorityTxs()
{
// How much of the block should be dedicated to high-priority transactions,
// included regardless of the fees they pay
unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
if (nBlockPrioritySize == 0) {
return;
}
// This vector will be sorted into a priority queue:
vector<TxCoinAgePriority> vecPriority;
TxCoinAgePriorityCompare pricomparer;
std::map<CTxMemPool::txiter, double, CTxMemPool::CompareIteratorByHash> waitPriMap;
typedef std::map<CTxMemPool::txiter, double, CTxMemPool::CompareIteratorByHash>::iterator waitPriIter;
double actualPriority = -1;
vecPriority.reserve(mempool.mapTx.size());
for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
mi != mempool.mapTx.end(); ++mi)
{
double dPriority = mi->GetPriority(nHeight);
CAmount dummy;
mempool.ApplyDeltas(mi->GetTx().GetHash(), dPriority, dummy);
vecPriority.push_back(TxCoinAgePriority(dPriority, mi));
}
std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer);
CTxMemPool::txiter iter;
while (!vecPriority.empty() && !blockFinished) { // add a tx from priority queue to fill the blockprioritysize
iter = vecPriority.front().second;
actualPriority = vecPriority.front().first;
std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer);
vecPriority.pop_back();
// If tx already in block, skip
if (inBlock.count(iter)) {
assert(false); // shouldn't happen for priority txs
continue;
}
// If tx is dependent on other mempool txs which haven't yet been included
// then put it in the waitSet
if (isStillDependent(iter)) {
waitPriMap.insert(std::make_pair(iter, actualPriority));
continue;
}
// If this tx fits in the block add it, otherwise keep looping
if (TestForBlock(iter)) {
AddToBlock(iter);
// If now that this txs is added we've surpassed our desired priority size
// or have dropped below the AllowFreeThreshold, then we're done adding priority txs
if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) {
return;
}
// This tx was successfully added, so
// add transactions that depend on this one to the priority queue to try again
for (CTxMemPool::txiter child : mempool.GetMemPoolChildren(iter))
{
waitPriIter wpiter = waitPriMap.find(child);
if (wpiter != waitPriMap.end()) {
vecPriority.push_back(TxCoinAgePriority(wpiter->second,child));
std::push_heap(vecPriority.begin(), vecPriority.end(), pricomparer);
waitPriMap.erase(wpiter);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Internal miner

View File

@ -148,8 +148,6 @@ private:
// Methods for how to add transactions to a block.
/** Add transactions based on modified feerate */
void addScoreTxs();
/** Add transactions based on tx "priority" */
void addPriorityTxs();
// helper function for addScoreTxs and addPriorityTxs
/** Test if tx will still "fit" in the block */

View File

@ -18,8 +18,7 @@ class CCoinsViewCache;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = MAX_BLOCK_SIZE;
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 = DEFAULT_BLOCK_MAX_SIZE / 2;
/** 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 */
@ -44,7 +43,6 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_
// Sanity check the magic numbers when we change them
static_assert(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE);
static_assert(DEFAULT_BLOCK_PRIORITY_SIZE <= DEFAULT_BLOCK_MAX_SIZE);
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
/**

View File

@ -388,7 +388,7 @@ public:
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByDescendantScore
>,
// sorted by score (for mining prioritization)
// sorted by score (for mining prioritisation)
boost::multi_index::ordered_unique<
boost::multi_index::tag<mining_score>,
boost::multi_index::identity<CTxMemPoolEntry>,
@ -673,17 +673,4 @@ public:
bool HaveCoins(const uint256 &txid) const;
};
// We want to sort transactions by coin age priority
typedef std::pair<double, CTxMemPool::txiter> TxCoinAgePriority;
struct TxCoinAgePriorityCompare
{
bool operator()(const TxCoinAgePriority& a, const TxCoinAgePriority& b)
{
if (a.first == b.first)
return CompareTxMemPoolEntryByScore()(*(b.second), *(a.second)); //Reverse order to make sort less than
return a.first < b.first;
}
};
#endif // BITCOIN_TXMEMPOOL_H