From 53ddbaed16448821857dbf6077f06c3e45c8bcde Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 22 Sep 2016 22:41:45 +1200 Subject: [PATCH 1/5] GBT: Support coinbasetxn instead of coinbasevalue Once a Zcash GBT spec has been written, we can re-enable coinbasevalue. --- src/rpcmining.cpp | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 7f2d01f88..8d6408f56 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -389,10 +389,10 @@ Value getblocktemplate(const Array& params, bool fHelp) " }\n" " ,...\n" " ],\n" - " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" - " \"flags\" : \"flags\" (string) \n" - " },\n" - " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n" +// " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" +// " \"flags\" : \"flags\" (string) \n" +// " },\n" +// " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n" " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" " \"target\" : \"xxxx\", (string) The hash target\n" " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" @@ -415,8 +415,15 @@ Value getblocktemplate(const Array& params, bool fHelp) LOCK(cs_main); + // Wallet is required because we support coinbasetxn + if (pwalletMain == NULL) { + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); + } + std::string strMode = "template"; Value lpval = Value::null; + // TODO: Re-enable coinbasevalue once a specification has been written + bool coinbasetxn = true; if (params.size() > 0) { const Object& oparam = params[0].get_obj(); @@ -529,7 +536,7 @@ Value getblocktemplate(const Array& params, bool fHelp) // Clear pindexPrev so future calls make a new block, despite any failures from here on pindexPrev = NULL; - // Store the pindexBest used before CreateNewBlock, to avoid races + // Store the pindexBest used before CreateNewBlockWithKey, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrevNew = chainActive.Tip(); nStart = GetTime(); @@ -540,12 +547,12 @@ Value getblocktemplate(const Array& params, bool fHelp) delete pblocktemplate; pblocktemplate = NULL; } - CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = CreateNewBlock(scriptDummy); + CReserveKey reservekey(pwalletMain); + pblocktemplate = CreateNewBlockWithKey(reservekey); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); - // Need to update only after we know CreateNewBlock succeeded + // Need to update only after we know CreateNewBlockWithKey succeeded pindexPrev = pindexPrevNew; } CBlock* pblock = &pblocktemplate->block; // pointer for convenience @@ -556,6 +563,7 @@ Value getblocktemplate(const Array& params, bool fHelp) static const Array aCaps = boost::assign::list_of("proposal"); + Value txCoinbase = Value::null; Array transactions; map setTxIndex; int i = 0; @@ -564,7 +572,7 @@ Value getblocktemplate(const Array& params, bool fHelp) uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; - if (tx.IsCoinBase()) + if (tx.IsCoinBase() && !coinbasetxn) continue; Object entry; @@ -585,7 +593,12 @@ Value getblocktemplate(const Array& params, bool fHelp) entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); - transactions.push_back(entry); + if (tx.IsCoinBase()) { + entry.push_back(Pair("required", true)); + txCoinbase = entry; + } else { + transactions.push_back(entry); + } } Object aux; @@ -606,8 +619,13 @@ Value getblocktemplate(const Array& params, bool fHelp) result.push_back(Pair("version", pblock->nVersion)); result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); - result.push_back(Pair("coinbaseaux", aux)); - result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); + if (coinbasetxn) { + assert(txCoinbase.type() == obj_type); + result.push_back(Pair("coinbasetxn", txCoinbase)); + } else { + result.push_back(Pair("coinbaseaux", aux)); + result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); + } result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); result.push_back(Pair("target", hashTarget.GetHex())); result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); From 89aa746ca12e36f28dc5f2b693f3e5d3d01c8842 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 23 Sep 2016 00:16:13 +1200 Subject: [PATCH 2/5] GBT: Add informational founders' reward value to coinbasetxn --- src/rpcmining.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 8d6408f56..acdf366a1 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -594,6 +594,11 @@ Value getblocktemplate(const Array& params, bool fHelp) entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); if (tx.IsCoinBase()) { + // Show founders' reward if it is required + if (pblock->vtx[0].vout.size() > 1) { + // Correct this if GetBlockTemplate changes the order + entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); + } entry.push_back(Pair("required", true)); txCoinbase = entry; } else { From 1628efedaf6c57e10661104a1ff6586e502658b2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 1 Oct 2016 17:26:59 +1300 Subject: [PATCH 3/5] GBT: Correct block header in proposals RPC test --- qa/rpc-tests/getblocktemplate_proposals.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index aca0cd749..0c9e7e4cc 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -71,9 +71,11 @@ def genmrklroot(leaflist): def template_to_bytes(tmpl, txlist): blkver = pack(' Date: Mon, 10 Oct 2016 15:24:00 -0500 Subject: [PATCH 4/5] GBT: Add RPC tests --- qa/pull-tester/rpc-tests.sh | 1 + qa/rpc-tests/getblocktemplate.py | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100755 qa/rpc-tests/getblocktemplate.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index b44df9d7b..13ddc461f 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -31,6 +31,7 @@ testScripts=( 'walletbackup.py' 'zcjoinsplit.py' 'zcjoinsplitdoublespend.py' + 'getblocktemplate.py' ); testScriptsExt=( 'bipdersig-p2p.py' diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py new file mode 100755 index 000000000..2610e257b --- /dev/null +++ b/qa/rpc-tests/getblocktemplate.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + + +class GetBlockTemplateTest(BitcoinTestFramework): + ''' + Test getblocktemplate. + ''' + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self, split=False): + self.nodes = start_nodes(2, self.options.tmpdir) + connect_nodes_bi(self.nodes,0,1) + self.is_network_split=False + self.sync_all() + + def run_test(self): + node = self.nodes[0] + node.generate(1) # Mine a block to leave initial block download + + # Test 1: Default to coinbasetxn + tmpl = node.getblocktemplate() + assert('coinbasetxn' in tmpl) + assert('coinbasevalue' not in tmpl) + + # Test 2: Get coinbasetxn if requested + tmpl = node.getblocktemplate({'capabilities': ['coinbasetxn']}) + assert('coinbasetxn' in tmpl) + assert('coinbasevalue' not in tmpl) + + # Test 3: coinbasevalue not supported if requested + tmpl = node.getblocktemplate({'capabilities': ['coinbasevalue']}) + assert('coinbasetxn' in tmpl) + assert('coinbasevalue' not in tmpl) + + # Test 4: coinbasevalue not supported if both requested + tmpl = node.getblocktemplate({'capabilities': ['coinbasetxn', 'coinbasevalue']}) + assert('coinbasetxn' in tmpl) + assert('coinbasevalue' not in tmpl) + + # Test 5: General checks + tmpl = node.getblocktemplate() + assert(len(tmpl['noncerange']) == 8) + + # Test 6: coinbasetxn checks + assert('foundersreward' in tmpl['coinbasetxn']) + assert(tmpl['coinbasetxn']['required']) + +if __name__ == '__main__': + GetBlockTemplateTest().main() From bc54cf06cc8ff965299af219adc0f05043138880 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 22 Oct 2016 15:36:38 -0500 Subject: [PATCH 5/5] Fix RPC test --- qa/rpc-tests/getblocktemplate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py index 2610e257b..c9777c0c7 100755 --- a/qa/rpc-tests/getblocktemplate.py +++ b/qa/rpc-tests/getblocktemplate.py @@ -48,7 +48,7 @@ class GetBlockTemplateTest(BitcoinTestFramework): # Test 5: General checks tmpl = node.getblocktemplate() - assert(len(tmpl['noncerange']) == 8) + assert(len(tmpl['noncerange']) == 16) # Test 6: coinbasetxn checks assert('foundersreward' in tmpl['coinbasetxn'])