diff --git a/qa/rpc-tests/wallet_overwintertx.py b/qa/rpc-tests/wallet_overwintertx.py index 84215eb6b..bad99a528 100755 --- a/qa/rpc-tests/wallet_overwintertx.py +++ b/qa/rpc-tests/wallet_overwintertx.py @@ -38,6 +38,11 @@ class WalletOverwinterTxTest (BitcoinTestFramework): # # Currently at block 198. The next block to be mined 199 is a Sprout block # + bci = self.nodes[0].getblockchaininfo() + assert_equal(bci['consensus']['chaintip'], '00000000') + assert_equal(bci['consensus']['nextblock'], '00000000') + assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending') + taddr0 = self.nodes[0].getnewaddress() taddr2 = self.nodes[2].getnewaddress() zaddr2 = self.nodes[2].z_getnewaddress() @@ -76,6 +81,10 @@ class WalletOverwinterTxTest (BitcoinTestFramework): # # Currently at block 199. The next block to be mined 200 is an Overwinter block # + bci = self.nodes[0].getblockchaininfo() + assert_equal(bci['consensus']['chaintip'], '00000000') + assert_equal(bci['consensus']['nextblock'], '5ba81b19') + assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending') # Send taddr to taddr tsendamount = Decimal('4.56') @@ -88,9 +97,14 @@ class WalletOverwinterTxTest (BitcoinTestFramework): myopid = self.nodes[0].z_sendmany(taddr0, recipients) txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) + # Mine the first Overwinter block self.sync_all() self.nodes[0].generate(1) self.sync_all() + bci = self.nodes[0].getblockchaininfo() + assert_equal(bci['consensus']['chaintip'], '5ba81b19') + assert_equal(bci['consensus']['nextblock'], '5ba81b19') + assert_equal(bci['upgrades']['5ba81b19']['status'], 'active') # Verify balance assert_equal(self.nodes[3].getbalance(), tsendamount) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index bbed8cba1..626c4724f 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -659,12 +659,45 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* return rv; } +static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height) +{ + UniValue rv(UniValue::VOBJ); + auto upgrade = NetworkUpgradeInfo[idx]; + rv.push_back(Pair("name", upgrade.strName)); + rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight)); + switch (NetworkUpgradeState(height, consensusParams, idx)) { + case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break; + case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break; + case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break; + } + rv.push_back(Pair("info", upgrade.strInfo)); + return rv; +} + +void NetworkUpgradeDescPushBack( + UniValue& networkUpgrades, + const Consensus::Params& consensusParams, + Consensus::UpgradeIndex idx, + int height) +{ + // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are + // hidden. This is used when network upgrade implementations are merged + // without specifying the activation height. + if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { + networkUpgrades.push_back(Pair( + HexInt(NetworkUpgradeInfo[idx].nBranchId), + NetworkUpgradeDesc(consensusParams, idx, height))); + } +} + UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getblockchaininfo\n" "Returns an object containing various state info regarding block chain processing.\n" + "\nNote that when the chain tip is at the last block before a network upgrade activation,\n" + "consensus.chaintip != consensus.nextblock.\n" "\nResult:\n" "{\n" " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" @@ -687,7 +720,19 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " },\n" " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" " }, ...\n" - " ]\n" + " ],\n" + " \"upgrades\": { (object) status of network upgrades\n" + " \"xxxx\" : { (string) branch ID of the upgrade\n" + " \"name\": \"xxxx\", (string) name of upgrade\n" + " \"activationheight\": xxxxxx, (numeric) block height of activation\n" + " \"status\": \"xxxx\", (string) status of upgrade\n" + " \"info\": \"xxxx\", (string) additional information about upgrade\n" + " }, ...\n" + " },\n" + " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n" + " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n" + " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n" + " }\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockchaininfo", "") @@ -722,6 +767,17 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); obj.push_back(Pair("softforks", softforks)); + UniValue upgrades(UniValue::VOBJ); + for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) { + NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight); + } + obj.push_back(Pair("upgrades", upgrades)); + + UniValue consensus(UniValue::VOBJ); + consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams)))); + consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams)))); + obj.push_back(Pair("consensus", consensus)); + if (fPruneMode) { CBlockIndex *block = chainActive.Tip();