Merge #8295: Mining-related fixups for 0.13.0

c1d61fb Add warning if -blockminsize is used. (Suhas Daftuar)
27362dd Remove -blockminsize option (Suhas Daftuar)
d2e46e1 Remove addScoreTxs() (Suhas Daftuar)
6dd4bc2 Exclude witness transactions in addPackageTxs() pre-segwit activation (Suhas Daftuar)
f15c2cd CreateNewBlock: add support for size-accounting to addPackageTxs (Suhas Daftuar)
This commit is contained in:
Wladimir J. van der Laan 2016-07-18 08:23:38 +02:00 committed by Alexander Block
parent bc257c1a08
commit f9f3b8d938
5 changed files with 31 additions and 77 deletions

View File

@ -21,7 +21,7 @@ CMD_GREP_DOCS = r"egrep -r -I 'HelpMessageOpt\(\"\-[^\"=]+?(=|\")' %s" % (CMD_RO
REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"') REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"')
REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")') REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")')
# list unsupported, deprecated and duplicate args as they need no documentation # list unsupported, deprecated and duplicate args as they need no documentation
SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay']) SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-blockminsize'])
def main(): def main():
used = check_output(CMD_GREP_ARGS, shell=True) used = check_output(CMD_GREP_ARGS, shell=True)

View File

@ -563,7 +563,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT)); strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT));
strUsage += HelpMessageGroup(_("Block creation options:")); 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("-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)); strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
if (showDebug) if (showDebug)
@ -1045,6 +1044,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (GetBoolArg("-whitelistalwaysrelay", false)) if (GetBoolArg("-whitelistalwaysrelay", false))
InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.")); InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay."));
if (mapArgs.count("-blockminsize"))
InitWarning("Unsupported argument -blockminsize ignored.");
// Checkmempool and checkblockindex default to true in regtest mode // Checkmempool and checkblockindex default to true in regtest mode
int ratio = std::min<int>(std::max<int>(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); int ratio = std::min<int>(std::max<int>(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
if (ratio != 0) { if (ratio != 0) {

View File

@ -82,11 +82,6 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
// Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MaxBlockSize(fDIP0001ActiveAtTip)-1000), nBlockMaxSize)); nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MaxBlockSize(fDIP0001ActiveAtTip)-1000), nBlockMaxSize));
// Minimum block size you want to create; block will be filled with free transactions
// until there are no more or the block reaches this size:
nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
} }
void BlockAssembler::resetBlock() void BlockAssembler::resetBlock()
@ -215,13 +210,26 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOp
return true; return true;
} }
// Block size and sigops have already been tested. Check that all transactions // Perform transaction-level checks before adding to block:
// are final. // - transaction finality (locktime)
bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package) // - premature witness (in case segwit transactions are added to mempool before
// segwit activation)
// - serialized size (in case -blockmaxsize is in use)
bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{ {
uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting
BOOST_FOREACH (const CTxMemPool::txiter it, package) { BOOST_FOREACH (const CTxMemPool::txiter it, package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false; return false;
if (!fIncludeWitness && !it->GetTx().wit.IsNull())
return false;
if (fNeedSizeAccounting) {
uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) {
return false;
}
nPotentialBlockSize += nTxSize;
}
} }
return true; return true;
} }
@ -289,62 +297,6 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
} }
} }
void BlockAssembler::addScoreTxs()
{
std::priority_queue<CTxMemPool::txiter, std::vector<CTxMemPool::txiter>, ScoreCompare> clearedTxs;
CTxMemPool::setEntries waitSet;
CTxMemPool::indexed_transaction_set::index<mining_score>::type::iterator mi = mempool.mapTx.get<mining_score>().begin();
CTxMemPool::txiter iter;
while (!blockFinished && (mi != mempool.mapTx.get<mining_score>().end() || !clearedTxs.empty()))
{
// If no txs that were previously postponed are available to try
// again, then try the next highest score tx
if (clearedTxs.empty()) {
iter = mempool.mapTx.project<0>(mi);
mi++;
}
// If a previously postponed tx is available to try again, then it
// has higher score than all untried so far txs
else {
iter = clearedTxs.top();
clearedTxs.pop();
}
// If tx already in block, skip (added by addPriorityTxs)
if (inBlock.count(iter)) {
continue;
}
// If tx is dependent on other mempool txs which haven't yet been included
// then put it in the waitSet
if (isStillDependent(iter)) {
waitSet.insert(iter);
continue;
}
// If the fee rate is below the min fee rate for mining, then we're done
// adding txs based on score (fee rate)
if (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(iter->GetTxSize()) && nBlockSize >= nBlockMinSize) {
return;
}
// If this tx fits in the block add it, otherwise keep looping
if (TestForBlock(iter)) {
AddToBlock(iter);
// This tx was successfully added, so
// add transactions that depend on this one to the priority queue to try again
BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter))
{
if (waitSet.count(child)) {
clearedTxs.push(child);
waitSet.erase(child);
}
}
}
}
}
void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
indexed_modified_transaction_set &mapModifiedTx) indexed_modified_transaction_set &mapModifiedTx)
{ {
@ -494,7 +446,7 @@ void BlockAssembler::addPackageTxs()
ancestors.insert(iter); ancestors.insert(iter);
// Test if all tx's are Final // Test if all tx's are Final
if (!TestPackageFinality(ancestors)) { if (!TestPackageTransactions(ancestors)) {
if (fUsingModified) { if (fUsingModified) {
mapModifiedTx.get<ancestor_score>().erase(modit); mapModifiedTx.get<ancestor_score>().erase(modit);
failedTx.insert(iter); failedTx.insert(iter);
@ -573,7 +525,7 @@ void BlockAssembler::addPriorityTxs()
// If now that this txs is added we've surpassed our desired priority size // 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 // or have dropped below the AllowFreeThreshold, then we're done adding priority txs
if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) { if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) {
return; break;
} }
// This tx was successfully added, so // This tx was successfully added, so

View File

@ -140,7 +140,7 @@ private:
CBlock* pblock; CBlock* pblock;
// Configuration parameters for the block size // Configuration parameters for the block size
unsigned int nBlockMaxSize, nBlockMinSize; unsigned int nBlockMaxSize;
// Information on the current status of the block // Information on the current status of the block
uint64_t nBlockSize; uint64_t nBlockSize;
@ -154,7 +154,7 @@ private:
int64_t nLockTimeCutoff; int64_t nLockTimeCutoff;
const CChainParams& chainparams; const CChainParams& chainparams;
// Variables used for addScoreTxs and addPriorityTxs // Variables used for addPriorityTxs
int lastFewTxs; int lastFewTxs;
bool blockFinished; bool blockFinished;
@ -171,14 +171,12 @@ private:
void AddToBlock(CTxMemPool::txiter iter); void AddToBlock(CTxMemPool::txiter iter);
// Methods for how to add transactions to a block. // Methods for how to add transactions to a block.
/** Add transactions based on modified feerate */
void addScoreTxs();
/** Add transactions based on tx "priority" */ /** Add transactions based on tx "priority" */
void addPriorityTxs(); void addPriorityTxs();
/** Add transactions based on feerate including unconfirmed ancestors */ /** Add transactions based on feerate including unconfirmed ancestors */
void addPackageTxs(); void addPackageTxs();
// helper function for addScoreTxs and addPriorityTxs // helper function for addPriorityTxs
/** Test if tx will still "fit" in the block */ /** Test if tx will still "fit" in the block */
bool TestForBlock(CTxMemPool::txiter iter); bool TestForBlock(CTxMemPool::txiter iter);
/** Test if tx still has unconfirmed parents not yet in block */ /** Test if tx still has unconfirmed parents not yet in block */
@ -189,8 +187,11 @@ private:
void onlyUnconfirmed(CTxMemPool::setEntries& testSet); void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
/** Test if a new package would "fit" in the block */ /** Test if a new package would "fit" in the block */
bool TestPackage(uint64_t packageSize, unsigned int packageSigOps); bool TestPackage(uint64_t packageSize, unsigned int packageSigOps);
/** Test if a set of transactions are all final */ /** Perform checks on each transaction in a package:
bool TestPackageFinality(const CTxMemPool::setEntries& package); * locktime, premature-witness, serialized size (if necessary)
* These checks should always succeed, and they're here
* only as an extra check in case of suboptimal node configuration */
bool TestPackageTransactions(const CTxMemPool::setEntries& package);
/** Return true if given transaction from mapTx has already been evaluated, /** Return true if given transaction from mapTx has already been evaluated,
* or if the transaction's cached data in mapTx is incorrect. */ * or if the transaction's cached data in mapTx is incorrect. */
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx); bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);

View File

@ -14,9 +14,8 @@
class CCoinsViewCache; class CCoinsViewCache;
/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ /** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; 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 **/ /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 10000; // was 50000 in 0.12.0 and it is 0 in Bitcoin since 0.12 static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 10000; // was 50000 in 0.12.0 and it is 0 in Bitcoin since 0.12
/** The maximum size for transactions we're willing to relay/mine */ /** The maximum size for transactions we're willing to relay/mine */