Auto merge of #4280 - oxarbitrage:issue2197, r=daira
Allow negative heights in RPC calls For issue https://github.com/zcash/zcash/issues/2197 Currently adding the feature to `getblock` and `getblockhash`. There is another candidate: `getblocksubsidy` however i want to have some review about these 2 first before repeating what could be a bad approach.
This commit is contained in:
commit
6c00a8ccf9
|
@ -95,5 +95,21 @@ class MerkleBlockTest(BitcoinTestFramework):
|
||||||
result = self.nodes[0].getblock(blockhash, 0)
|
result = self.nodes[0].getblock(blockhash, 0)
|
||||||
assert(c in string.hexdigits for c in result) # verbosity 0 returns raw hex
|
assert(c in string.hexdigits for c in result) # verbosity 0 returns raw hex
|
||||||
|
|
||||||
|
# Test getblock heights including negatives relative to the head
|
||||||
|
assert_equal(self.nodes[0].getblock("0")["height"], 0)
|
||||||
|
assert_raises(JSONRPCException, self.nodes[0].getblock, ["108"])
|
||||||
|
assert_equal(self.nodes[0].getblock("107")["height"], 107)
|
||||||
|
assert_equal(self.nodes[0].getblock("-1")["height"], 107)
|
||||||
|
assert_equal(self.nodes[0].getblock("-2")["height"], 106)
|
||||||
|
assert_equal(self.nodes[0].getblock("-20")["height"], 88)
|
||||||
|
assert_equal(self.nodes[0].getblock("-107")["height"], 1)
|
||||||
|
assert_equal(self.nodes[0].getblock("-108")["height"], 0)
|
||||||
|
assert_raises(JSONRPCException, self.nodes[0].getblock, ["-109"])
|
||||||
|
assert_raises(JSONRPCException, self.nodes[0].getblock, ["-0"])
|
||||||
|
|
||||||
|
# Test getblockhash negative heights
|
||||||
|
assert_equal(self.nodes[0].getblockhash(-1), self.nodes[0].getblockhash(107))
|
||||||
|
assert_equal(self.nodes[0].getblockhash(-2), self.nodes[0].getblockhash(106))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
MerkleBlockTest().main()
|
MerkleBlockTest().main()
|
||||||
|
|
|
@ -578,7 +578,7 @@ UniValue getblockhash(const UniValue& params, bool fHelp)
|
||||||
"getblockhash index\n"
|
"getblockhash index\n"
|
||||||
"\nReturns hash of block in best-block-chain at index provided.\n"
|
"\nReturns hash of block in best-block-chain at index provided.\n"
|
||||||
"\nArguments:\n"
|
"\nArguments:\n"
|
||||||
"1. index (numeric, required) The block index\n"
|
"1. index (numeric, required) The block index. If negative then -1 is the last known valid block\n"
|
||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
"\"hash\" (string) The block hash\n"
|
"\"hash\" (string) The block hash\n"
|
||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
|
@ -589,6 +589,11 @@ UniValue getblockhash(const UniValue& params, bool fHelp)
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
int nHeight = params[0].get_int();
|
int nHeight = params[0].get_int();
|
||||||
|
|
||||||
|
if (nHeight < 0) {
|
||||||
|
nHeight += chainActive.Height() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (nHeight < 0 || nHeight > chainActive.Height())
|
if (nHeight < 0 || nHeight > chainActive.Height())
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||||
|
|
||||||
|
@ -662,7 +667,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
|
||||||
"If verbosity is 1, returns an Object with information about the block.\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"
|
"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. Height can be negative where -1 is the last known valid block\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"
|
"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 verbosity = 0):\n"
|
"\nResult (for verbosity = 0):\n"
|
||||||
"\"data\" (string) A string that is serialized, hex-encoded data for the block.\n"
|
"\"data\" (string) A string that is serialized, hex-encoded data for the block.\n"
|
||||||
|
@ -708,7 +713,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
|
||||||
// If height is supplied, find the hash
|
// If height is supplied, find the hash
|
||||||
if (strHash.size() < (2 * sizeof(uint256))) {
|
if (strHash.size() < (2 * sizeof(uint256))) {
|
||||||
// std::stoi allows characters, whereas we want to be strict
|
// std::stoi allows characters, whereas we want to be strict
|
||||||
regex r("[[:digit:]]+");
|
regex r("(?:(-?)[1-9][0-9]*|[0-9]+)");
|
||||||
if (!regex_match(strHash, r)) {
|
if (!regex_match(strHash, r)) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
|
||||||
}
|
}
|
||||||
|
@ -721,9 +726,14 @@ UniValue getblock(const UniValue& params, bool fHelp)
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nHeight < 0) {
|
||||||
|
nHeight += chainActive.Height() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (nHeight < 0 || nHeight > chainActive.Height()) {
|
if (nHeight < 0 || nHeight > chainActive.Height()) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
strHash = chainActive[nHeight]->GetBlockHash().GetHex();
|
strHash = chainActive[nHeight]->GetBlockHash().GetHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,7 +310,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||||
* getblock
|
* getblock
|
||||||
*/
|
*/
|
||||||
BOOST_CHECK_THROW(CallRPC("getblock too many args"), runtime_error);
|
BOOST_CHECK_THROW(CallRPC("getblock too many args"), runtime_error);
|
||||||
BOOST_CHECK_THROW(CallRPC("getblock -1"), runtime_error);
|
BOOST_CHECK_NO_THROW(CallRPC("getblock -1")); // negative heights relative are allowed
|
||||||
|
BOOST_CHECK_THROW(CallRPC("getblock -2147483647"), runtime_error); // allowed, but chain tip - height < 0
|
||||||
BOOST_CHECK_THROW(CallRPC("getblock 2147483647"), runtime_error); // allowed, but > height of active chain tip
|
BOOST_CHECK_THROW(CallRPC("getblock 2147483647"), runtime_error); // allowed, but > height of active chain tip
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue