From 8b1d430007fa8f104a885918ec38bae56a160650 Mon Sep 17 00:00:00 2001 From: Jianping Wu Date: Tue, 5 Mar 2019 21:10:29 -0800 Subject: [PATCH] WIP: Implemented getblockheaderbyheight. --- src/cn_utils/cryptonote_config.h | 2 +- src/rpc/blockchain.cpp | 82 ++++++++++++++++++++++++++++++++ src/rpc/mining.cpp | 6 +-- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/cn_utils/cryptonote_config.h b/src/cn_utils/cryptonote_config.h index f88ba44c2..8c002967a 100644 --- a/src/cn_utils/cryptonote_config.h +++ b/src/cn_utils/cryptonote_config.h @@ -40,7 +40,7 @@ #define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0 #define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60 #define CURRENT_TRANSACTION_VERSION 1 -#define CURRENT_BLOCK_MAJOR_VERSION 1 +#define CURRENT_BLOCK_MAJOR_VERSION 8 #define CURRENT_BLOCK_MINOR_VERSION 0 #define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2 diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 79ca48bb1..884e8b7c1 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -702,6 +702,88 @@ UniValue getblockheader(const JSONRPCRequest& request) return blockheaderToJSON(pblockindex); } + +// Cryptonote RPC API: getblockheaderbyheight +UniValue getblockheaderbyheight(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) + throw std::runtime_error( + "getblockheader \"hash\" ( verbose )\n" + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" + "If verbose is true, returns an Object with information about blockheader .\n" + "\nArguments:\n" + "1. \"height\" (numeric, required) The block height\n" + "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" + " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" + " \"height\" : n, (numeric) The block height or index\n" + " \"version\" : n, (numeric) The block version\n" + " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" + " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" + " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"nonce\" : n, (numeric) The nonce\n" + " \"bits\" : \"1d00ffff\", (string) The bits\n" + " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" + " \"nTx\" : n, (numeric) The number of transactions in the block.\n" + " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" + " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n" + "}\n" + "\nResult (for verbose=false):\n" + "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" + "\nExamples:\n" + + HelpExampleCli("getblockheader", "\"e2acdf2dd19a702e5d12a925f1e984b01e47a933562ca893656d4afb38b44ee3\"") + + HelpExampleRpc("getblockheader", "\"e2acdf2dd19a702e5d12a925f1e984b01e47a933562ca893656d4afb38b44ee3\"") + ); + + LOCK(cs_main); + + int nHeight = request.params[0].get_int(); + if (nHeight < 0 || nHeight > chainActive.Height()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + + CBlockIndex* pblockindex = chainActive[nHeight]; + CBlock block; + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { + throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk"); + } + + CTransactionRef coinbaseTx = block.vtx[0]; + if (!coinbaseTx->IsCoinBase()) { + throw JSONRPCError(RPC_MISC_ERROR, "Could not find coinbase"); + } + //TODO: easier way to do this? + CAmount coinbaseValue = coinbaseTx->GetValueOut(); + + UniValue result(UniValue::VOBJ); + + // TODO: read major/minor versions from cn header. + result.push_back(Pair("major_version", (uint64_t)0)); + result.push_back(Pair("minor_version", (uint64_t)0)); + + result.push_back(Pair("timestamp", (uint64_t)pblockindex->nTime)); + result.push_back(Pair("prev_hash", pblockindex->pprev->GetBlockHash().GetHex())); + result.push_back(Pair("nonce", (uint64_t)pblockindex->nNonce)); + result.push_back(Pair("orphan_status", false)); + result.push_back(Pair("height", (uint64_t)pblockindex->nHeight)); + const uint64_t depth = chainActive.Height() - nHeight + 1; // Same as confirmations. + result.push_back(Pair("depth", (uint64_t)depth)); + result.push_back(Pair("hash", pblockindex->GetBlockHash().GetHex())); + result.push_back(Pair("difficulty", GetDifficulty(pblockindex))); + + // TODO: implement cumulative_difficulty + result.push_back(Pair("cumulative_difficulty", 0)); + result.push_back(Pair("reward", (uint64_t)coinbaseValue)); + result.push_back(Pair("block_size", (int)::GetBlockWeight(block))); + result.push_back(Pair("num_txes", (uint64_t)pblockindex->nTx)); + result.push_back(Pair("pow_hash", pblockindex->GetBlockPoWHash().GetHex())); + result.push_back(Pair("long_term_weight", 0.0)); // Not implemented + return result; +} + UniValue getblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 69c4ca5fe..6eabac444 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -938,9 +938,9 @@ UniValue getblocktemplate(const JSONRPCRequest& request) UniValue result(UniValue::VOBJ); const double difficulty = ConvertNBitsToDiff(pblock->nBits); result.push_back(Pair("blocktemplate_blob", pblock->hashPrevBlock.GetHex())); - result.push_back(Pair("difficulty", std::to_string(difficulty))); - result.push_back(Pair("height", std::to_string(height))); - result.push_back(Pair("reserved_offset", std::to_string(reserved_offset))); + result.push_back(Pair("difficulty", (double)difficulty)); + result.push_back(Pair("height", (uint64_t)height)); + result.push_back(Pair("reserved_offset", (uint64_t)reserved_offset)); // Kevacoin specific entries. Not used for now and may be useful in the future. result.push_back(Pair("rules", aRules));