Auto merge of #3179 - bitcartel:backport_transaction_details_in_getblock_v2bitcartel, r=str4d

Add improvements to getblock RPC output

Includes and supercedes #3095. Includes code cherry-picked from bitcoin/bitcoin#8704.
This commit is contained in:
Homu
2018-05-01 10:19:10 -07:00
3 changed files with 47 additions and 15 deletions

View File

@@ -7,6 +7,7 @@
# Test merkleblock fetch/validation # Test merkleblock fetch/validation
# #
import string
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_raises, \ from test_framework.util import assert_equal, assert_raises, \
@@ -86,5 +87,13 @@ class MerkleBlockTest(BitcoinTestFramework):
# ...or if we have a -txindex # ...or if we have a -txindex
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof([txid_spent])), [txid_spent]) assert_equal(self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof([txid_spent])), [txid_spent])
# Quick test of getblock using blockhash and different levels of verbosity
result = self.nodes[0].getblock(blockhash, 2)
coinbase_txid = result["tx"][0]["txid"]
result = self.nodes[0].getblock(blockhash, 1)
assert_equal(coinbase_txid, result["tx"][0]) # verbosity 1 only lists txids
result = self.nodes[0].getblock(blockhash, 0)
assert(c in string.hexdigits for c in result) # verbosity 0 returns raw hex
if __name__ == '__main__': if __name__ == '__main__':
MerkleBlockTest().main() MerkleBlockTest().main()

View File

@@ -394,13 +394,16 @@ UniValue getblock(const UniValue& params, bool fHelp)
{ {
if (fHelp || params.size() < 1 || params.size() > 2) if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error( throw runtime_error(
"getblock \"hash|height\" ( verbose )\n" "getblock \"hash|height\" ( verbosity )\n"
"\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n" "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for the block.\n"
"If verbose is true, returns an Object with information about block <hash|height>.\n" "If verbosity is 1, returns an Object with information about the block.\n"
"If verbosity is 2, returns an Object with information about the block and information about each transaction. \n"
"\nArguments:\n" "\nArguments:\n"
"1. \"hash|height\" (string, required) The block hash or height\n" "1. \"hash|height\" (string, required) The block hash or height\n"
"2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" "2. verbosity (numeric, optional, default=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data\n"
"\nResult (for verbose = true):\n" "\nResult (for verbosity = 0):\n"
"\"data\" (string) A string that is serialized, hex-encoded data for the block.\n"
"\nResult (for verbosity = 1):\n"
"{\n" "{\n"
" \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n"
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
@@ -419,11 +422,17 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
"}\n" "}\n"
"\nResult (for verbose=false):\n" "\nResult (for verbosity = 2):\n"
"\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" "{\n"
" ..., Same output as verbosity = 1.\n"
" \"tx\" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result.\n"
" ,...\n"
" ],\n"
" ,... Same output as verbosity = 1.\n"
"}\n"
"\nExamples:\n" "\nExamples:\n"
+ HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleCli("getblock", "\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\"")
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblock", "\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\"")
+ HelpExampleCli("getblock", "12800") + HelpExampleCli("getblock", "12800")
+ HelpExampleRpc("getblock", "12800") + HelpExampleRpc("getblock", "12800")
); );
@@ -456,9 +465,18 @@ UniValue getblock(const UniValue& params, bool fHelp)
uint256 hash(uint256S(strHash)); uint256 hash(uint256S(strHash));
bool fVerbose = true; int verbosity = 1;
if (params.size() > 1) if (params.size() > 1) {
fVerbose = params[1].get_bool(); if(params[1].isNum()) {
verbosity = params[1].get_int();
} else {
verbosity = params[1].get_bool() ? 1 : 0;
}
}
if (verbosity < 0 || verbosity > 2) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbosity must be in range from 0 to 2");
}
if (mapBlockIndex.count(hash) == 0) if (mapBlockIndex.count(hash) == 0)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
@@ -472,7 +490,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
if(!ReadBlockFromDisk(block, pblockindex)) if(!ReadBlockFromDisk(block, pblockindex))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
if (!fVerbose) if (verbosity == 0)
{ {
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
ssBlock << block; ssBlock << block;
@@ -480,7 +498,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
return strHex; return strHex;
} }
return blockToJSON(block, pblockindex); return blockToJSON(block, pblockindex, verbosity >= 2);
} }
UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)

View File

@@ -291,6 +291,11 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
BOOST_CHECK_THROW(CallRPC("getblock 2147483648"), runtime_error); // not allowed, > int32 used for nHeight BOOST_CHECK_THROW(CallRPC("getblock 2147483648"), runtime_error); // not allowed, > int32 used for nHeight
BOOST_CHECK_THROW(CallRPC("getblock 100badchars"), runtime_error); BOOST_CHECK_THROW(CallRPC("getblock 100badchars"), runtime_error);
BOOST_CHECK_NO_THROW(CallRPC("getblock 0")); BOOST_CHECK_NO_THROW(CallRPC("getblock 0"));
BOOST_CHECK_NO_THROW(CallRPC("getblock 0 0"));
BOOST_CHECK_NO_THROW(CallRPC("getblock 0 1"));
BOOST_CHECK_NO_THROW(CallRPC("getblock 0 2"));
BOOST_CHECK_THROW(CallRPC("getblock 0 -1"), runtime_error); // bad verbosity
BOOST_CHECK_THROW(CallRPC("getblock 0 3"), runtime_error); // bad verbosity
} }
BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance) BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance)