diff --git a/doc/release-notes.md b/doc/release-notes.md --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -3,3 +3,6 @@ This release includes the following features and fixes: + + - New `minerfundaddresses` subfield of `coinbasetxn` in `getblocktemplate` to + enable easy fetching of valid addresses for infrastructure funding. diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -657,6 +659,15 @@ UniValue aux(UniValue::VOBJ); aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())); + UniValue coinbasetxn(UniValue::VOBJ); + UniValue minerFundList(UniValue::VARR); + for (auto fundDestination : GetMinerFundWhitelist( + config.GetChainParams().GetConsensus(), pindexPrev)) { + minerFundList.push_back( + EncodeCashAddr(fundDestination, config.GetChainParams())); + } + coinbasetxn.pushKV("minerfundaddresses", minerFundList); + arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); UniValue aMutable(UniValue::VARR); @@ -672,6 +683,7 @@ result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); result.pushKV("transactions", transactions); result.pushKV("coinbaseaux", aux); + result.pushKV("coinbasetxn", coinbasetxn); result.pushKV("coinbasevalue", int64_t(coinbasevalue / SATOSHI)); result.pushKV("longpollid", ::ChainActive().Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)); diff --git a/test/functional/abc-magnetic-anomaly-mining.py b/test/functional/abc-magnetic-anomaly-mining.py --- a/test/functional/abc-magnetic-anomaly-mining.py +++ b/test/functional/abc-magnetic-anomaly-mining.py @@ -98,7 +98,6 @@ tmpl = mining_node.getblocktemplate() assert 'proposal' in tmpl['capabilities'] - assert 'coinbasetxn' not in tmpl # Check the template transaction metadata and ordering last_txid = 0 diff --git a/test/functional/abc_mining_basic.py b/test/functional/abc_mining_basic.py --- a/test/functional/abc_mining_basic.py +++ b/test/functional/abc_mining_basic.py @@ -22,6 +22,7 @@ from decimal import Decimal AXION_ACTIVATION_TIME = 2000000600 +MINER_FUND_ADDR = 'bchreg:pqnqv9lt7e5vjyp0w88zf2af0l92l8rxdgd35g0pkl' class AbcMiningRPCTest(BitcoinTestFramework): @@ -36,13 +37,6 @@ node = self.nodes[0] address = node.get_deterministic_priv_key().address - # Move MTP forward to axion activation - node.setmocktime(AXION_ACTIVATION_TIME) - node.generatetoaddress(6, address) - assert_equal( - node.getblockchaininfo()['mediantime'], - AXION_ACTIVATION_TIME) - # Assert the results of getblocktemplate have expected values. Keys not # in 'expected' are not checked. def assert_getblocktemplate(expected): @@ -55,6 +49,23 @@ for key, value in expected.items(): assert_equal(blockTemplate[key], value) + # Move block time to just before axion activation + node.setmocktime(AXION_ACTIVATION_TIME) + node.generatetoaddress(5, address) + + # Before axion activation, the miner fund list is empty + assert_getblocktemplate({ + 'coinbasetxn': { + 'minerfundaddresses': [], + }, + }) + + # Move MTP forward to axion activation + node.generatetoaddress(1, address) + assert_equal( + node.getblockchaininfo()['mediantime'], + AXION_ACTIVATION_TIME) + def get_best_coinbase(): return node.getblock(node.getbestblockhash(), 2)['tx'][0] @@ -66,6 +77,11 @@ # them are covered in mining_basic.py assert_equal(node.getmempoolinfo()['size'], 0) assert_getblocktemplate({ + 'coinbasetxn': { + # We expect to start seeing the miner fund addresses since the + # next block will start enforcing them. + 'minerfundaddresses': [MINER_FUND_ADDR], + }, # Although the coinbase value need not necessarily be the same as # the last block due to halvings and fees, we know this to be true # since we are not crossing a halving boundary and there are no @@ -86,6 +102,9 @@ assert_equal(total, block_reward) assert_getblocktemplate({ + 'coinbasetxn': { + 'minerfundaddresses': [MINER_FUND_ADDR], + }, # Again, we assume the coinbase value is the same as prior blocks. 'coinbasevalue': block_reward * COIN, 'mintime': AXION_ACTIVATION_TIME + 1, @@ -95,6 +114,9 @@ node.setmocktime(AXION_ACTIVATION_TIME + 1) node.generatetoaddress(6, address) assert_getblocktemplate({ + 'coinbasetxn': { + 'minerfundaddresses': [MINER_FUND_ADDR], + }, 'coinbasevalue': block_reward * COIN, 'mintime': AXION_ACTIVATION_TIME + 2, }) diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py --- a/test/functional/mining_basic.py +++ b/test/functional/mining_basic.py @@ -90,7 +90,6 @@ tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'proposal' in tmpl['capabilities'] - assert 'coinbasetxn' not in tmpl next_height = int(tmpl["height"]) coinbase_tx = create_coinbase(height=next_height)