2015-05-27 12:08:46 +00:00
|
|
|
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
2015-04-06 16:13:07 +00:00
|
|
|
//
|
|
|
|
// This file is part of Bytecoin.
|
|
|
|
//
|
|
|
|
// Bytecoin is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Bytecoin is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "RPCTestNode.h"
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
#include <future>
|
2015-04-06 16:13:07 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <thread>
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
#include "Common/StringTools.h"
|
|
|
|
#include "cryptonote_core/cryptonote_format_utils.h"
|
2015-04-06 16:13:07 +00:00
|
|
|
#include "node_rpc_proxy/NodeRpcProxy.h"
|
2015-05-27 12:08:46 +00:00
|
|
|
#include "rpc/core_rpc_server_commands_defs.h"
|
|
|
|
#include "rpc/HttpClient.h"
|
|
|
|
#include "rpc/JsonRpc.h"
|
2015-04-06 16:13:07 +00:00
|
|
|
|
|
|
|
#include "Logger.h"
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
using namespace CryptoNote;
|
2015-04-06 16:13:07 +00:00
|
|
|
using namespace System;
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
namespace Tests {
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
RPCTestNode::RPCTestNode(uint16_t port, System::Dispatcher& d) :
|
|
|
|
m_rpcPort(port), m_dispatcher(d), m_httpClient(d, "127.0.0.1", port) {
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RPCTestNode::startMining(size_t threadsCount, const std::string& address) {
|
|
|
|
LOG_DEBUG("startMining()");
|
2015-05-27 12:08:46 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
COMMAND_RPC_START_MINING::request req;
|
|
|
|
COMMAND_RPC_START_MINING::response resp;
|
|
|
|
req.miner_address = address;
|
|
|
|
req.threads_count = threadsCount;
|
|
|
|
|
|
|
|
invokeJsonCommand(m_httpClient, "/start_mining", req, resp);
|
|
|
|
if (resp.status != CORE_RPC_STATUS_OK) {
|
|
|
|
throw std::runtime_error(resp.status);
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::cout << "startMining() RPC call fail: " << e.what();
|
2015-04-06 16:13:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
bool RPCTestNode::getBlockTemplate(const std::string& minerAddress, CryptoNote::Block& blockTemplate, uint64_t& difficulty) {
|
|
|
|
LOG_DEBUG("getBlockTemplate()");
|
|
|
|
|
|
|
|
try {
|
|
|
|
COMMAND_RPC_GETBLOCKTEMPLATE::request req;
|
|
|
|
COMMAND_RPC_GETBLOCKTEMPLATE::response rsp;
|
|
|
|
req.wallet_address = minerAddress;
|
|
|
|
req.reserve_size = 0;
|
|
|
|
|
|
|
|
JsonRpc::invokeJsonRpcCommand(m_httpClient, "getblocktemplate", req, rsp);
|
|
|
|
if (rsp.status != CORE_RPC_STATUS_OK) {
|
|
|
|
throw std::runtime_error(rsp.status);
|
|
|
|
}
|
|
|
|
|
|
|
|
difficulty = rsp.difficulty;
|
|
|
|
|
|
|
|
CryptoNote::blobdata blockBlob = ::Common::asString(::Common::fromHex(rsp.blocktemplate_blob));
|
|
|
|
return CryptoNote::parse_and_validate_block_from_blob(blockBlob, blockTemplate);
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
LOG_ERROR("JSON-RPC call startMining() failed: " + std::string(e.what()));
|
2015-04-06 16:13:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
bool RPCTestNode::submitBlock(const std::string& block) {
|
|
|
|
LOG_DEBUG("submitBlock()");
|
|
|
|
|
|
|
|
try {
|
|
|
|
COMMAND_RPC_SUBMITBLOCK::request req;
|
|
|
|
COMMAND_RPC_SUBMITBLOCK::response res;
|
|
|
|
req.push_back(block);
|
|
|
|
JsonRpc::invokeJsonRpcCommand(m_httpClient, "submitblock", req, res);
|
|
|
|
if (res.status != CORE_RPC_STATUS_OK) {
|
|
|
|
throw std::runtime_error(res.status);
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
LOG_ERROR("RPC call of submit_block returned error: " + std::string(e.what()));
|
2015-04-06 16:13:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-05-27 12:08:46 +00:00
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RPCTestNode::stopMining() {
|
|
|
|
LOG_DEBUG("stopMining()");
|
2015-05-27 12:08:46 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
COMMAND_RPC_STOP_MINING::request req;
|
|
|
|
COMMAND_RPC_STOP_MINING::response resp;
|
|
|
|
invokeJsonCommand(m_httpClient, "/stop_mining", req, resp);
|
|
|
|
if (resp.status != CORE_RPC_STATUS_OK) {
|
|
|
|
throw std::runtime_error(resp.status);
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::cout << "stopMining() RPC call fail: " << e.what();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RPCTestNode::getTailBlockId(crypto::hash& tailBlockId) {
|
|
|
|
LOG_DEBUG("getTailBlockId()");
|
|
|
|
|
|
|
|
try {
|
|
|
|
COMMAND_RPC_GET_LAST_BLOCK_HEADER::request req;
|
|
|
|
COMMAND_RPC_GET_LAST_BLOCK_HEADER::response rsp;
|
|
|
|
JsonRpc::invokeJsonRpcCommand(m_httpClient, "getlastblockheader", req, rsp);
|
|
|
|
if (rsp.status != CORE_RPC_STATUS_OK) {
|
|
|
|
throw std::runtime_error(rsp.status);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ::Common::podFromHex(rsp.block_header.hash, tailBlockId);
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
LOG_ERROR("JSON-RPC call getTailBlockId() failed: " + std::string(e.what()));
|
2015-04-06 16:13:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RPCTestNode::makeINode(std::unique_ptr<CryptoNote::INode>& node) {
|
2015-05-27 12:08:46 +00:00
|
|
|
std::unique_ptr<CryptoNote::INode> newNode(new CryptoNote::NodeRpcProxy("127.0.0.1", m_rpcPort));
|
|
|
|
|
|
|
|
std::promise<std::error_code> prom;
|
|
|
|
std::future<std::error_code> fut(prom.get_future());
|
|
|
|
|
|
|
|
newNode->init([&](std::error_code ec) {
|
|
|
|
std::promise<std::error_code> localProm(std::move(prom));
|
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
if (ec) {
|
|
|
|
LOG_ERROR("init error: " + ec.message() + ':' + TO_STRING(ec.value()));
|
|
|
|
} else {
|
|
|
|
LOG_DEBUG("NodeRPCProxy on port " + TO_STRING(m_rpcPort) + " initialized");
|
|
|
|
}
|
2015-05-27 12:08:46 +00:00
|
|
|
|
|
|
|
localProm.set_value(ec);
|
2015-04-06 16:13:07 +00:00
|
|
|
});
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
if (!fut.get()) {
|
|
|
|
node = std::move(newNode);
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-04-06 16:13:07 +00:00
|
|
|
|
|
|
|
bool RPCTestNode::stopDaemon() {
|
2015-05-27 12:08:46 +00:00
|
|
|
try {
|
|
|
|
LOG_DEBUG("stopDaemon()");
|
|
|
|
COMMAND_RPC_STOP_DAEMON::request req;
|
|
|
|
COMMAND_RPC_STOP_DAEMON::response resp;
|
|
|
|
invokeJsonCommand(m_httpClient, "/stop_daemon", req, resp);
|
|
|
|
if (resp.status != CORE_RPC_STATUS_OK) {
|
|
|
|
throw std::runtime_error(resp.status);
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
std::cout << "stopDaemon() RPC call fail: " << e.what();
|
2015-04-06 16:13:07 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2015-05-27 12:08:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t RPCTestNode::getLocalHeight() {
|
|
|
|
try {
|
|
|
|
CryptoNote::COMMAND_RPC_GET_INFO::request req;
|
|
|
|
CryptoNote::COMMAND_RPC_GET_INFO::response rsp;
|
|
|
|
invokeJsonCommand(m_httpClient, "/getinfo", req, rsp);
|
|
|
|
if (rsp.status == CORE_RPC_STATUS_OK) {
|
|
|
|
return rsp.height;
|
|
|
|
}
|
|
|
|
} catch (std::exception&) {
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|