diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index efe09d1b6..6286b90a3 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -25,6 +25,11 @@ #include #include #include +#ifdef ENABLE_WALLET +#include +#include +#endif + #include #include @@ -372,6 +377,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) UniValue lpval = NullUniValue; std::set setClientRules; int64_t nMaxVersionPreVB = -1; + UniValue aMutable(UniValue::VARR); + bool wantsCoinbaseTxn = false; if (!request.params[0].isNull()) { const UniValue& oparam = request.params[0].get_obj(); @@ -386,6 +393,17 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); lpval = find_value(oparam, "longpollid"); + const UniValue& capval = find_value(oparam, "capabilities"); + if (capval.isArray()) { + for (std::size_t i = 0; i < capval.size(); ++i) + if (capval[i].get_str() == "coinbase/append") // should be coinbase/* ? we dont' care what they do to the coinbase + aMutable.push_back(capval[i]); +#ifdef ENABLE_WALLET + else if (capval[i].get_str() == "coinbasetxn") + wantsCoinbaseTxn = true; +#endif + } + if (strMode == "proposal") { const UniValue& dataval = find_value(oparam, "data"); @@ -519,8 +537,20 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) fLastTemplateSupportsSegwit = fSupportsSegwit; // Create new block - CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit); + CScript newBlockScript = CScript() << OP_TRUE; +#ifdef ENABLE_WALLET + if (wantsCoinbaseTxn) { + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + if (!wallet) + throw JSONRPCError(RPC_INVALID_PARAMS, "No wallet to comply with coinbasetxn request."); + std::shared_ptr coinbase_script; + wallet->GetScriptForMining(coinbase_script); // tops up and locks inside + if (!coinbase_script) + throw JSONRPCError(RPC_INVALID_PARAMS, "Unable to acquire address for coinbasetxn request."); + newBlockScript = coinbase_script->reserveScript; + } +#endif + pblocktemplate = BlockAssembler(Params()).CreateNewBlock(newBlockScript, fSupportsSegwit); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); @@ -539,6 +569,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) const bool fPreSegWit = (ThresholdState::ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache)); UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); + UniValue result(UniValue::VOBJ); UniValue transactions(UniValue::VARR); std::map setTxIndex; @@ -548,7 +579,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; - if (tx.IsCoinBase()) + auto isCoinbase = tx.IsCoinBase(); + if (isCoinbase && !wantsCoinbaseTxn) continue; UniValue entry(UniValue::VOBJ); @@ -575,7 +607,10 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) entry.pushKV("sigops", nTxSigOps); entry.pushKV("weight", GetTransactionWeight(tx)); - transactions.push_back(entry); + if (isCoinbase) + result.pushKV("coinbasetxn", entry); + else + transactions.push_back(entry); } UniValue aux(UniValue::VOBJ); @@ -583,12 +618,11 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - UniValue aMutable(UniValue::VARR); aMutable.push_back("time"); aMutable.push_back("transactions"); aMutable.push_back("prevblock"); + aMutable.push_back("submit/coinbase"); - UniValue result(UniValue::VOBJ); result.pushKV("capabilities", aCaps); UniValue aRules(UniValue::VARR);