Compare commits
26 commits
master
...
bug/api-do
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3402f9a726 | ||
|
|
d2cb8cd846 | ||
|
|
54a7e5b757 | ||
|
|
75e6f9abd5 | ||
|
|
c4f3f37075 | ||
|
|
ac2c9e16e6 | ||
|
|
863e8a0d91 | ||
|
|
aab2dac1c2 | ||
|
|
6bc8a10c67 | ||
|
|
94092093f8 | ||
|
|
2e35053668 | ||
|
|
a2fab62a1a | ||
|
|
22239bbd60 | ||
|
|
d45b631079 | ||
|
|
87c2f5a10f | ||
|
|
ca32d13192 | ||
|
|
6febed5a36 | ||
|
|
be580e0c34 | ||
|
|
922327f98c | ||
|
|
94b518cb7a | ||
|
|
4f1d1f9c34 | ||
|
|
b3b8c926c1 | ||
|
|
b908d7f12f | ||
|
|
9fc3536638 | ||
|
|
16431b3be5 | ||
|
|
6e0064aefe |
10 changed files with 225 additions and 41 deletions
|
|
@ -18,7 +18,42 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
rpc_client::rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls) :
|
||||
struct rpc_reply {
|
||||
uint16_t status;
|
||||
std::string body;
|
||||
};
|
||||
|
||||
class rpc_connection {
|
||||
public:
|
||||
rpc_connection(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls);
|
||||
|
||||
std::string send_post_request(std::string method, std::string params, bool show_log);
|
||||
std::string get_url() const;
|
||||
|
||||
protected:
|
||||
|
||||
std::string url;
|
||||
std::string user;
|
||||
std::string password;
|
||||
bool debug_rpc_calls;
|
||||
|
||||
std::string protocol;
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string target;
|
||||
std::string authorization;
|
||||
|
||||
uint32_t request_id;
|
||||
|
||||
private:
|
||||
rpc_reply send_post_request(std::string body, bool show_log);
|
||||
|
||||
boost::beast::net::io_context ioc;
|
||||
boost::beast::net::ip::tcp::resolver resolver;
|
||||
boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> results;
|
||||
};
|
||||
|
||||
rpc_connection::rpc_connection(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls) :
|
||||
url(_url),
|
||||
user(_user),
|
||||
password(_password),
|
||||
|
|
@ -61,6 +96,11 @@ rpc_client::rpc_client(std::string _url, std::string _user, std::string _passwor
|
|||
}
|
||||
}
|
||||
|
||||
std::string rpc_connection::get_url() const
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) {
|
||||
if (reply_str.empty()) {
|
||||
wlog("RPC call ${function}, empty reply string", ("function", __FUNCTION__));
|
||||
|
|
@ -125,7 +165,7 @@ std::string rpc_client::retrieve_value_from_reply(std::string reply_str, std::st
|
|||
return "";
|
||||
}
|
||||
|
||||
std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log) {
|
||||
std::string rpc_connection::send_post_request(std::string method, std::string params, bool show_log) {
|
||||
std::stringstream body;
|
||||
|
||||
request_id = request_id + 1;
|
||||
|
|
@ -164,7 +204,7 @@ std::string rpc_client::send_post_request(std::string method, std::string params
|
|||
return "";
|
||||
}
|
||||
|
||||
rpc_reply rpc_client::send_post_request(std::string body, bool show_log) {
|
||||
rpc_reply rpc_connection::send_post_request(std::string body, bool show_log) {
|
||||
|
||||
// These object is used as a context for ssl connection
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12_client);
|
||||
|
|
@ -247,4 +287,114 @@ rpc_reply rpc_client::send_post_request(std::string body, bool show_log) {
|
|||
return reply;
|
||||
}
|
||||
|
||||
rpc_client::rpc_client(const std::vector<std::string> &_urls, const std::vector<std::string> &_users, const std::vector<std::string> &_passwords, bool _debug_rpc_calls):
|
||||
debug_rpc_calls(_debug_rpc_calls)
|
||||
{
|
||||
FC_ASSERT(_urls.size());
|
||||
FC_ASSERT(_users.size() == _urls.size() && _passwords.size() == _urls.size());
|
||||
for (size_t i=0; i < _urls.size(); i++)
|
||||
connections.push_back(new rpc_connection(_urls[i], _users[i], _passwords[i], _debug_rpc_calls));
|
||||
n_active_conn = 0;
|
||||
schedule_connection_selection();
|
||||
}
|
||||
|
||||
void rpc_client::schedule_connection_selection()
|
||||
{
|
||||
fc::time_point now = fc::time_point::now();
|
||||
static const int64_t time_to_next_conn_selection = 2000000;
|
||||
fc::time_point next_wakeup = now + fc::microseconds(time_to_next_conn_selection);
|
||||
connection_selection_task = fc::schedule([this] {
|
||||
select_connection();
|
||||
}, next_wakeup, "SON RPC connection selection");
|
||||
}
|
||||
|
||||
void rpc_client::select_connection()
|
||||
{
|
||||
//ilog("n_active_rpc_client=${n}", ("n", n_active_rpc_client));
|
||||
static const int t_limit = 10*1000000, // 10 sec
|
||||
quality_diff_threshold = 10000; // 10 ms
|
||||
|
||||
FC_ASSERT(connections.size());
|
||||
|
||||
int best_n = -1;
|
||||
int best_quality = -1;
|
||||
|
||||
std::vector<uint64_t> head_block_numbers;
|
||||
head_block_numbers.resize(connections.size());
|
||||
|
||||
std::vector<int> qualities;
|
||||
qualities.resize(connections.size());
|
||||
|
||||
for (size_t n=0; n < connections.size(); n++) {
|
||||
rpc_connection *conn = connections[n];
|
||||
int quality = 0;
|
||||
head_block_numbers[n] = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
// make the ping
|
||||
fc::time_point t_sent = fc::time_point::now();
|
||||
uint64_t head_block_number = ping(*conn);
|
||||
fc::time_point t_received = fc::time_point::now();
|
||||
if (head_block_number != std::numeric_limits<uint64_t>::max()) {
|
||||
int t = (t_received - t_sent).count();
|
||||
t += rand() % 10;
|
||||
FC_ASSERT(t != -1);
|
||||
head_block_numbers[n] = head_block_number;
|
||||
if (t < t_limit)
|
||||
quality = t_limit - t; // the less time, the higher quality
|
||||
|
||||
// look for the best quality
|
||||
if (quality > best_quality) {
|
||||
best_n = n;
|
||||
best_quality = quality;
|
||||
}
|
||||
}
|
||||
qualities[n] = quality;
|
||||
}
|
||||
|
||||
FC_ASSERT(best_n != -1 && best_quality != -1);
|
||||
if (best_n != n_active_conn) { // if the best client is not the current one, ...
|
||||
uint64_t active_head_block_number = head_block_numbers[n_active_conn];
|
||||
if ((active_head_block_number == std::numeric_limits<uint64_t>::max() // ...and the current one has no known head block...
|
||||
|| head_block_numbers[best_n] >= active_head_block_number) // ...or the best client's head is more recent than the current, ...
|
||||
&& best_quality > qualities[n_active_conn] + quality_diff_threshold) { // ...and the new client's quality exceeds current more than by threshold
|
||||
n_active_conn = best_n; // ...then select new one
|
||||
ilog("!!! rpc connection reselected, now ${n}", ("n", n_active_conn));
|
||||
}
|
||||
}
|
||||
|
||||
schedule_connection_selection();
|
||||
}
|
||||
|
||||
rpc_connection &rpc_client::get_active_connection() const
|
||||
{
|
||||
return *connections[n_active_conn];
|
||||
}
|
||||
|
||||
std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log)
|
||||
{
|
||||
return send_post_request(get_active_connection(), method, params, show_log);
|
||||
}
|
||||
|
||||
std::string rpc_client::send_post_request(rpc_connection &conn, std::string method, std::string params, bool show_log)
|
||||
{
|
||||
return conn.send_post_request(method, params, show_log);
|
||||
}
|
||||
|
||||
std::string rpc_client::get_connection_url(const rpc_connection &conn)
|
||||
{
|
||||
return conn.get_url();
|
||||
}
|
||||
|
||||
rpc_client::~rpc_client()
|
||||
{
|
||||
try {
|
||||
if (connection_selection_task.valid())
|
||||
connection_selection_task.cancel_and_wait(__FUNCTION__);
|
||||
} catch (fc::canceled_exception &) {
|
||||
//Expected exception. Move along.
|
||||
} catch (fc::exception &e) {
|
||||
edump((e.to_detail_string()));
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -3,44 +3,42 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <fc/thread/future.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/beast/core.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
struct rpc_reply {
|
||||
uint16_t status;
|
||||
std::string body;
|
||||
};
|
||||
class rpc_connection;
|
||||
|
||||
class rpc_client {
|
||||
public:
|
||||
rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls);
|
||||
rpc_client(const std::vector<std::string> &_urls, const std::vector<std::string> &_users, const std::vector<std::string> &_passwords, bool _debug_rpc_calls);
|
||||
~rpc_client();
|
||||
|
||||
protected:
|
||||
std::string retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx);
|
||||
std::string retrieve_value_from_reply(std::string reply_str, std::string value_path);
|
||||
bool debug_rpc_calls;
|
||||
std::string send_post_request(std::string method, std::string params, bool show_log);
|
||||
|
||||
std::string url;
|
||||
std::string user;
|
||||
std::string password;
|
||||
bool debug_rpc_calls;
|
||||
static std::string send_post_request(rpc_connection &conn, std::string method, std::string params, bool show_log);
|
||||
|
||||
std::string protocol;
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string target;
|
||||
std::string authorization;
|
||||
static std::string retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx);
|
||||
static std::string retrieve_value_from_reply(std::string reply_str, std::string value_path);
|
||||
|
||||
uint32_t request_id;
|
||||
static std::string get_connection_url(const rpc_connection &conn);
|
||||
|
||||
private:
|
||||
rpc_reply send_post_request(std::string body, bool show_log);
|
||||
std::vector<rpc_connection*> connections;
|
||||
int n_active_conn;
|
||||
fc::future<void> connection_selection_task;
|
||||
|
||||
boost::beast::net::io_context ioc;
|
||||
boost::beast::net::ip::tcp::resolver resolver;
|
||||
boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> results;
|
||||
rpc_connection &get_active_connection() const;
|
||||
|
||||
void select_connection();
|
||||
void schedule_connection_selection();
|
||||
virtual uint64_t ping(rpc_connection &conn) const = 0;
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
bitcoin_rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls);
|
||||
bitcoin_rpc_client(const std::vector<std::string> &_urls, const std::vector<std::string> &_users, const std::vector<std::string> &_passwords, bool _debug_rpc_calls);
|
||||
|
||||
std::string createwallet(const std::string &wallet_name);
|
||||
uint64_t estimatesmartfee(uint16_t conf_target = 128);
|
||||
|
|
@ -58,6 +58,8 @@ public:
|
|||
std::string walletlock();
|
||||
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60);
|
||||
|
||||
virtual uint64_t ping(rpc_connection &conn) const override;
|
||||
|
||||
private:
|
||||
std::string ip;
|
||||
uint32_t rpc_port;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
|
||||
class ethereum_rpc_client : public rpc_client {
|
||||
public:
|
||||
ethereum_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls);
|
||||
ethereum_rpc_client(const std::vector<std::string> &urls, const std::vector<std::string> &user_names, const std::vector<std::string> &passwords, bool debug_rpc_calls);
|
||||
|
||||
std::string eth_blockNumber();
|
||||
std::string eth_get_block_by_number(std::string block_number, bool full_block);
|
||||
|
|
@ -34,6 +34,8 @@ public:
|
|||
std::string eth_send_transaction(const std::string ¶ms);
|
||||
std::string eth_send_raw_transaction(const std::string ¶ms);
|
||||
std::string eth_get_transaction_receipt(const std::string ¶ms);
|
||||
|
||||
virtual uint64_t ping(rpc_connection &conn) const override;
|
||||
};
|
||||
|
||||
class sidechain_net_handler_ethereum : public sidechain_net_handler {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
|
||||
class hive_rpc_client : public rpc_client {
|
||||
public:
|
||||
hive_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls);
|
||||
hive_rpc_client(const std::vector<std::string> &urls, const std::vector<std::string> &user_names, const std::vector<std::string> &passwords, bool debug_rpc_calls);
|
||||
|
||||
std::string account_history_api_get_transaction(std::string transaction_id);
|
||||
std::string block_api_get_block(uint32_t block_number);
|
||||
|
|
@ -30,6 +30,8 @@ public:
|
|||
std::string get_head_block_time();
|
||||
std::string get_is_test_net();
|
||||
std::string get_last_irreversible_block_num();
|
||||
|
||||
virtual uint64_t ping(rpc_connection &conn) const override;
|
||||
};
|
||||
|
||||
class sidechain_net_handler_hive : public sidechain_net_handler {
|
||||
|
|
@ -48,13 +50,12 @@ public:
|
|||
virtual optional<asset> estimate_withdrawal_transaction_fee() const override;
|
||||
|
||||
private:
|
||||
std::string rpc_url;
|
||||
std::vector<std::string> rpc_urls;
|
||||
std::string rpc_user;
|
||||
std::string rpc_password;
|
||||
std::string wallet_account_name;
|
||||
|
||||
hive_rpc_client *rpc_client;
|
||||
|
||||
hive::chain_id_type chain_id;
|
||||
hive::network network_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
"Tuple of [Ethereum public key, Ethereum private key] (may specify multiple times)");
|
||||
|
||||
cli.add_options()("hive-sidechain-enabled", bpo::value<bool>()->default_value(false), "Hive sidechain handler enabled");
|
||||
cli.add_options()("hive-node-rpc-url", bpo::value<string>()->default_value("127.0.0.1:28090"), "Hive node RPC URL [http[s]://]host[:port]");
|
||||
cli.add_options()("hive-node-rpc-url", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR("127.0.0.1:28090"), "Hive node RPC URL [http[s]://]host[:port]");
|
||||
cli.add_options()("hive-node-rpc-user", bpo::value<string>(), "Hive node RPC user");
|
||||
cli.add_options()("hive-node-rpc-password", bpo::value<string>(), "Hive node RPC password");
|
||||
cli.add_options()("hive-wallet-account-name", bpo::value<string>(), "Hive wallet account name");
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
|
||||
// =============================================================================
|
||||
|
||||
bitcoin_rpc_client::bitcoin_rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls) :
|
||||
rpc_client(_url, _user, _password, _debug_rpc_calls) {
|
||||
bitcoin_rpc_client::bitcoin_rpc_client(const std::vector<std::string> &_urls, const std::vector<std::string> &_users, const std::vector<std::string> &_passwords, bool _debug_rpc_calls) :
|
||||
rpc_client(_urls, _users, _passwords, _debug_rpc_calls) {
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) {
|
||||
|
|
@ -244,6 +244,11 @@ bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_
|
|||
return true;
|
||||
}
|
||||
|
||||
uint64_t bitcoin_rpc_client::ping(rpc_connection &conn) const {
|
||||
ilog("!!!bitcoin_rpc_client::ping() ${url}", ("url", get_connection_url(conn)));
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
zmq_listener::zmq_listener(std::string _ip, uint32_t _zmq) :
|
||||
|
|
@ -353,7 +358,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
|||
url = url + "/wallet/" + wallet_name;
|
||||
}
|
||||
|
||||
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls));
|
||||
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client({url}, {rpc_user}, {rpc_password}, debug_rpc_calls));
|
||||
if (!wallet_name.empty()) {
|
||||
bitcoin_client->loadwallet(wallet_name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
ethereum_rpc_client::ethereum_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) :
|
||||
rpc_client(url, user_name, password, debug_rpc_calls) {
|
||||
ethereum_rpc_client::ethereum_rpc_client(const std::vector<std::string> &urls, const std::vector<std::string> &user_names, const std::vector<std::string> &passwords, bool debug_rpc_calls) :
|
||||
rpc_client(urls, user_names, passwords, debug_rpc_calls) {
|
||||
}
|
||||
|
||||
std::string ethereum_rpc_client::eth_blockNumber() {
|
||||
|
|
@ -121,6 +121,11 @@ std::string ethereum_rpc_client::eth_get_transaction_receipt(const std::string &
|
|||
return send_post_request("eth_getTransactionReceipt", "[\"" + params + "\"]", debug_rpc_calls);
|
||||
}
|
||||
|
||||
uint64_t ethereum_rpc_client::ping(rpc_connection &conn) const {
|
||||
ilog("!!!ethereum_rpc_client::ping() ${url}", ("url", get_connection_url(conn)));
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
|
||||
sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
|
||||
sidechain_net_handler(_plugin, options) {
|
||||
sidechain = sidechain_type::ethereum;
|
||||
|
|
@ -155,7 +160,7 @@ sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidecha
|
|||
}
|
||||
}
|
||||
|
||||
rpc_client = new ethereum_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls);
|
||||
rpc_client = new ethereum_rpc_client({rpc_url}, {rpc_user}, {rpc_password}, debug_rpc_calls);
|
||||
|
||||
const std::string chain_id_str = rpc_client->get_chain_id();
|
||||
if (chain_id_str.empty()) {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
hive_rpc_client::hive_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) :
|
||||
rpc_client(url, user_name, password, debug_rpc_calls) {
|
||||
hive_rpc_client::hive_rpc_client(const std::vector<std::string> &urls, const std::vector<std::string> &user_names, const std::vector<std::string> &passwords, bool debug_rpc_calls) :
|
||||
rpc_client(urls, user_names, passwords, debug_rpc_calls) {
|
||||
}
|
||||
|
||||
std::string hive_rpc_client::account_history_api_get_transaction(std::string transaction_id) {
|
||||
|
|
@ -112,6 +112,20 @@ std::string hive_rpc_client::get_last_irreversible_block_num() {
|
|||
return retrieve_value_from_reply(reply_str, "last_irreversible_block_num");
|
||||
}
|
||||
|
||||
uint64_t hive_rpc_client::ping(rpc_connection &conn) const {
|
||||
ilog("!!!hive_rpc_client::ping() ${url}", ("url", get_connection_url(conn)));
|
||||
const std::string reply = send_post_request(conn, "database_api.get_dynamic_global_properties", "", debug_rpc_calls);
|
||||
if (!reply.empty()) {
|
||||
std::stringstream ss(reply);
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
if (json.count("result")) {
|
||||
return json.get<uint64_t>("result.head_block_number");
|
||||
}
|
||||
}
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
|
||||
sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
|
||||
sidechain_net_handler(_plugin, options) {
|
||||
sidechain = sidechain_type::hive;
|
||||
|
|
@ -120,7 +134,7 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi
|
|||
debug_rpc_calls = options.at("debug-rpc-calls").as<bool>();
|
||||
}
|
||||
|
||||
rpc_url = options.at("hive-node-rpc-url").as<std::string>();
|
||||
rpc_urls = options.at("hive-node-rpc-url").as<std::vector<std::string>>();
|
||||
if (options.count("hive-rpc-user")) {
|
||||
rpc_user = options.at("hive-rpc-user").as<std::string>();
|
||||
} else {
|
||||
|
|
@ -146,11 +160,17 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi
|
|||
}
|
||||
}
|
||||
|
||||
rpc_client = new hive_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls);
|
||||
std::vector<std::string> rpc_users, rpc_passwords;
|
||||
for (size_t i=0; i < rpc_urls.size(); i++) {
|
||||
rpc_users.push_back(rpc_user);
|
||||
rpc_passwords.push_back(rpc_password);
|
||||
}
|
||||
|
||||
rpc_client = new hive_rpc_client(rpc_urls, rpc_users, rpc_passwords, debug_rpc_calls);
|
||||
|
||||
const std::string chain_id_str = rpc_client->get_chain_id();
|
||||
if (chain_id_str.empty()) {
|
||||
elog("No Hive node running at ${url}", ("url", rpc_url));
|
||||
elog("No Hive node running at ${url}", ("url", rpc_urls[0]));
|
||||
FC_ASSERT(false);
|
||||
}
|
||||
chain_id = chain_id_type(chain_id_str);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ sub formatDocComment
|
|||
for (my $i = 0; $i < @{$doc}; ++$i)
|
||||
{
|
||||
my $docElement = $doc->[$i];
|
||||
if (ref($docElement) ne 'HASH') { continue }
|
||||
|
||||
if ($docElement->{params})
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue