support coinbasetxn capability in getblocktemplate

This commit is contained in:
Brannon King 2019-06-17 09:44:18 -06:00
parent 36ccf3e903
commit 24269e177f

View file

@ -25,6 +25,11 @@
#include <utilstrencodings.h>
#include <validationinterface.h>
#include <warnings.h>
#ifdef ENABLE_WALLET
#include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#endif
#include <memory>
#include <stdint.h>
@ -372,6 +377,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
UniValue lpval = NullUniValue;
std::set<std::string> 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<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
if (!wallet)
throw JSONRPCError(RPC_INVALID_PARAMS, "No wallet to comply with coinbasetxn request.");
std::shared_ptr<CReserveScript> 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<uint256, int64_t> 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);