Commit 360562c7 authored by Pierre Kim's avatar Pierre Kim

Complete RPC command 'f_block_json'

parent 78883ee2
......@@ -18,6 +18,7 @@
#include "CryptoNoteCore/Currency.h"
#include "CryptoNoteCore/MinerConfig.h"
#include "CryptoNoteProtocol/CryptoNoteProtocolHandler.h"
#include "BlockchainExplorer\BlockchainExplorerDataBuilder.h"
#include "P2p/NetNode.h"
#include "P2p/NetNodeConfig.h"
#include "Rpc/RpcServer.h"
......@@ -236,7 +237,8 @@ int main(int argc, char* argv[])
CryptoNote::CryptoNoteProtocolHandler cprotocol(currency, dispatcher, ccore, nullptr, logManager);
CryptoNote::NodeServer p2psrv(dispatcher, cprotocol, logManager);
CryptoNote::RpcServer rpcServer(dispatcher, logManager, ccore, p2psrv, cprotocol);
BlockchainExplorerDataBuilder blkExplorer(ccore, cprotocol);
CryptoNote::RpcServer rpcServer(dispatcher, logManager, ccore, p2psrv, cprotocol, blkExplorer);
cprotocol.set_p2p_endpoint(&p2psrv);
ccore.set_cryptonote_protocol(&cprotocol);
......
......@@ -28,6 +28,21 @@ struct STATUS_STRUCT {
}
};
struct f_transaction_short_response {
std::string hash;
uint64_t fee;
uint64_t amount_out;
uint64_t size;
void serialize(ISerializer &s) {
KV_MEMBER(hash)
KV_MEMBER(fee)
KV_MEMBER(amount_out)
KV_MEMBER(size)
}
};
struct f_block_short_response {
uint64_t timestamp;
uint64_t difficulty;
......@@ -46,6 +61,85 @@ struct f_block_short_response {
}
};
struct f_block_details_response {
uint8_t major_version;
uint8_t minor_version;
uint64_t timestamp;
std::string prev_hash;
uint32_t nonce;
bool orphan_status;
uint32_t height;
uint64_t depth;
std::string hash;
uint64_t difficulty;
uint64_t reward;
uint64_t blockSize;
size_t sizeMedian;
uint64_t effectiveSizeMedian;
uint64_t transactionsCumulativeSize;
std::string alreadyGeneratedCoins;
uint64_t alreadyGeneratedTransactions;
uint64_t baseReward;
double penalty;
uint64_t totalFeeAmount;
std::vector<f_transaction_short_response> transactions;
void serialize(ISerializer &s) {
KV_MEMBER(major_version)
KV_MEMBER(minor_version)
KV_MEMBER(timestamp)
KV_MEMBER(prev_hash)
KV_MEMBER(nonce)
KV_MEMBER(orphan_status)
KV_MEMBER(height)
KV_MEMBER(depth)
KV_MEMBER(hash)
KV_MEMBER(difficulty)
KV_MEMBER(reward)
KV_MEMBER(blockSize)
KV_MEMBER(sizeMedian)
KV_MEMBER(effectiveSizeMedian)
KV_MEMBER(transactionsCumulativeSize)
KV_MEMBER(alreadyGeneratedCoins)
KV_MEMBER(alreadyGeneratedTransactions)
KV_MEMBER(baseReward)
KV_MEMBER(penalty)
KV_MEMBER(transactions)
KV_MEMBER(totalFeeAmount)
}
};
struct currency_base_coin {
std::string name;
std::string git;
void serialize(ISerializer &s) {
KV_MEMBER(name)
KV_MEMBER(git)
}
};
struct F_COMMAND_RPC_GET_BLOCK_DETAILS {
struct request {
std::string hash;
void serialize(ISerializer &s) {
KV_MEMBER(hash)
}
};
struct response {
f_block_details_response block;
std::string status;
void serialize(ISerializer &s) {
KV_MEMBER(block)
KV_MEMBER(status)
}
};
};
struct COMMAND_RPC_GET_HEIGHT {
typedef EMPTY_STRUCT request;
......
......@@ -92,8 +92,8 @@ std::unordered_map<std::string, RpcServer::RpcHandler<RpcServer::HandlerFunction
{ "/json_rpc", { std::bind(&RpcServer::processJsonRpcRequest, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), true } }
};
RpcServer::RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery) :
HttpServer(dispatcher, log), logger(log, "RpcServer"), m_core(c), m_p2p(p2p), m_protocolQuery(protocolQuery) {
RpcServer::RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery, BlockchainExplorerDataBuilder& blkExplorer) :
HttpServer(dispatcher, log), logger(log, "RpcServer"), m_core(c), m_p2p(p2p), m_protocolQuery(protocolQuery), m_blkExplorer(blkExplorer){
}
void RpcServer::processRequest(const HttpRequest& request, HttpResponse& response) {
......@@ -134,6 +134,7 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse&
static std::unordered_map<std::string, RpcServer::RpcHandler<JsonMemberMethod>> jsonRpcHandlers = {
{ "f_blocks_list_json",{ makeMemberMethod(&RpcServer::f_on_blocks_list_json), false } },
{ "f_block_json",{ makeMemberMethod(&RpcServer::f_on_block_json), false } },
{ "getblockcount", { makeMemberMethod(&RpcServer::on_getblockcount), true } },
{ "on_getblockhash", { makeMemberMethod(&RpcServer::on_getblockhash), false } },
{ "getblocktemplate", { makeMemberMethod(&RpcServer::on_getblocktemplate), false } },
......@@ -670,7 +671,6 @@ bool RpcServer::f_on_blocks_list_json(const COMMAND_RPC_BLOCKS_LIST_JSON::reques
"Internal error: can't get block by height. Height = " + std::to_string(i) + '.' };
}
//BlockDetails blkDetails = m_core.getBlockDetails(block_hash);
size_t blkSize;
difficulty_type difficulty;
m_core.getBlockSize(block_hash, blkSize);
......@@ -694,6 +694,102 @@ bool RpcServer::f_on_blocks_list_json(const COMMAND_RPC_BLOCKS_LIST_JSON::reques
return true;
}
bool RpcServer::f_on_block_json(const F_COMMAND_RPC_GET_BLOCK_DETAILS::request& req, F_COMMAND_RPC_GET_BLOCK_DETAILS::response& res) {
Hash hash;
try {
uint32_t height = boost::lexical_cast<uint32_t>(req.hash);
hash = m_core.getBlockIdByHeight(static_cast<uint32_t>(height));
}
catch (boost::bad_lexical_cast &) {
if (!parse_hash256(req.hash, hash)) {
throw JsonRpc::JsonRpcError{
CORE_RPC_ERROR_CODE_WRONG_PARAM,
"Failed to parse hex representation of block hash. Hex = " + req.hash + '.' };
}
}
Block blk;
if (!m_core.getBlockByHash(hash, blk)) {
throw JsonRpc::JsonRpcError{
CORE_RPC_ERROR_CODE_INTERNAL_ERROR,
"Internal error: can't get block by hash. Hash = " + req.hash + '.' };
}
BlockDetails blkDetails;
m_blkExplorer.fillBlockDetails(blk, blkDetails);
if (blk.baseTransaction.inputs.front().type() != typeid(BaseInput)) {
throw JsonRpc::JsonRpcError{
CORE_RPC_ERROR_CODE_INTERNAL_ERROR,
"Internal error: coinbase transaction in the block has the wrong type" };
}
block_header_response block_header;
res.block.height = boost::get<BaseInput>(blk.baseTransaction.inputs.front()).blockIndex;
fill_block_header_response(blk, false, res.block.height, hash, block_header);
res.block.major_version = block_header.major_version;
res.block.minor_version = block_header.minor_version;
res.block.timestamp = block_header.timestamp;
res.block.prev_hash = block_header.prev_hash;
res.block.nonce = block_header.nonce;
res.block.hash = Common::podToHex(hash);
res.block.depth = m_core.get_current_blockchain_height() - res.block.height;
m_core.getBlockDifficulty(res.block.height, res.block.difficulty);
res.block.transactionsCumulativeSize = blkDetails.transactionsCumulativeSize;
res.block.alreadyGeneratedCoins = std::to_string(blkDetails.alreadyGeneratedCoins);
res.block.alreadyGeneratedTransactions = blkDetails.alreadyGeneratedTransactions;
res.block.reward = block_header.reward;
res.block.sizeMedian = blkDetails.sizeMedian;
res.block.blockSize = blkDetails.blockSize;
res.block.orphan_status = blkDetails.isOrphaned;
uint64_t maxReward = 0;
uint64_t currentReward = 0;
int64_t emissionChange = 0;
size_t blockGrantedFullRewardZone = 10000; //CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE
res.block.effectiveSizeMedian = std::max(res.block.sizeMedian, blockGrantedFullRewardZone);
res.block.baseReward = blkDetails.baseReward;
res.block.penalty = blkDetails.penalty;
// Base transaction adding
f_transaction_short_response transaction_short;
transaction_short.hash = Common::podToHex(getObjectHash(blk.baseTransaction));
transaction_short.fee = 0;
transaction_short.amount_out = getOutputAmount(blk.baseTransaction);
transaction_short.size = getObjectBinarySize(blk.baseTransaction);
res.block.transactions.push_back(transaction_short);
std::list<Crypto::Hash> missed_txs;
std::list<Transaction> txs;
m_core.getTransactions(blk.transactionHashes, txs, missed_txs);
res.block.totalFeeAmount = 0;
for (const Transaction& tx : txs) {
f_transaction_short_response transaction_short;
uint64_t amount_in = getInputAmount(tx);
uint64_t amount_out = getOutputAmount(tx);
transaction_short.hash = Common::podToHex(getObjectHash(tx));
transaction_short.fee = amount_in - amount_out;
transaction_short.amount_out = amount_out;
transaction_short.size = getObjectBinarySize(tx);
res.block.transactions.push_back(transaction_short);
res.block.totalFeeAmount += transaction_short.fee;
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
bool RpcServer::enableCors(const std::vector<std::string> domains) {
m_cors_domains = domains;
return true;
......
......@@ -10,6 +10,8 @@
#include <Logging/LoggerRef.h>
#include "CoreRpcServerCommandsDefinitions.h"
#include "BlockchainExplorer\BlockchainExplorerDataBuilder.h"
namespace CryptoNote {
class core;
......@@ -18,7 +20,7 @@ class ICryptoNoteProtocolQuery;
class RpcServer : public HttpServer {
public:
RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery);
RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery, BlockchainExplorerDataBuilder& blkExplorer);
typedef std::function<bool(RpcServer*, const HttpRequest& request, HttpResponse& response)> HandlerFunction;
bool enableCors(const std::vector<std::string> domains);
......@@ -65,6 +67,7 @@ private:
bool on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res);
bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res);
bool f_on_blocks_list_json(const COMMAND_RPC_BLOCKS_LIST_JSON::request& req, COMMAND_RPC_BLOCKS_LIST_JSON::response& res);
bool f_on_block_json(const F_COMMAND_RPC_GET_BLOCK_DETAILS::request& req, F_COMMAND_RPC_GET_BLOCK_DETAILS::response& res);
void fill_block_header_response(const Block& blk, bool orphan_status, uint64_t height, const Crypto::Hash& hash, block_header_response& responce);
......@@ -73,6 +76,8 @@ private:
NodeServer& m_p2p;
const ICryptoNoteProtocolQuery& m_protocolQuery;
std::vector<std::string> m_cors_domains;
BlockchainExplorerDataBuilder& m_blkExplorer;
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment