[mining] segwit option must be set in GBT

Calling getblocktemplate without the segwit rule specified is most
likely a client error, since it results in lower fees for the miner.
Prevent this client error by failing getblocktemplate if called without
the segwit rule specified.
This commit is contained in:
John Newbery
2018-11-26 11:17:38 -05:00
parent 5f23460c7e
commit 0025c9eae4
10 changed files with 30 additions and 62 deletions

View File

@@ -311,7 +311,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
" https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
" https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
{
{"template_request", RPCArg::Type::OBJ, /* opt */ true, /* default_val */ "", "A json object in the following spec",
{"template_request", RPCArg::Type::OBJ, /* opt */ false, /* default_val */ "", "A json object in the following spec",
{
{"mode", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
{"capabilities", RPCArg::Type::ARR, /* opt */ true, /* default_val */ "", "A list of strings",
@@ -319,7 +319,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
{"support", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
},
},
{"rules", RPCArg::Type::ARR, /* opt */ true, /* default_val */ "", "A list of strings",
{"rules", RPCArg::Type::ARR, /* opt */ false, /* default_val */ "", "A list of strings",
{
{"support", RPCArg::Type::STR, /* opt */ true, /* default_val */ "", "client side supported softfork deployment"},
},
@@ -503,21 +503,17 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
}
const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
// If the caller is indicating segwit support, then allow CreateNewBlock()
// to select witness transactions, after segwit activates (otherwise
// don't).
bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end();
// GBT must be called with 'segwit' set in the rules
if (setClientRules.count(segwit_info.name) != 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "getblocktemplate must be called with the segwit rule set (call with {\"rules\": [\"segwit\"]})");
}
// Update block
static CBlockIndex* pindexPrev;
static int64_t nStart;
static std::unique_ptr<CBlockTemplate> pblocktemplate;
// Cache whether the last invocation was with segwit support, to avoid returning
// a segwit-block to a non-segwit caller.
static bool fLastTemplateSupportsSegwit = true;
if (pindexPrev != chainActive.Tip() ||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) ||
fLastTemplateSupportsSegwit != fSupportsSegwit)
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
{
// Clear pindexPrev so future calls make a new block, despite any failures from here on
pindexPrev = nullptr;
@@ -526,11 +522,10 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrevNew = chainActive.Tip();
nStart = GetTime();
fLastTemplateSupportsSegwit = fSupportsSegwit;
// Create new block
CScript scriptDummy = CScript() << OP_TRUE;
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit);
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@@ -682,7 +677,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
result.pushKV("bits", strprintf("%08x", pblock->nBits));
result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));
if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
if (!pblocktemplate->vchCoinbaseCommitment.empty()) {
result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()));
}