Basic RPC communication with Ethereum node established

This commit is contained in:
serkixenos 2022-06-30 00:21:04 +02:00
parent da46b16560
commit 57ccbdffd4
10 changed files with 116 additions and 1065 deletions

View file

@ -18,6 +18,8 @@ add_library( peerplays_sidechain
bitcoin/sign_bitcoin_transaction.cpp
common/rpc_client.cpp
common/utils.cpp
ethereum/encoders.cpp
ethereum/decoders.cpp
ethereum/transaction.cpp
ethereum/types.cpp
hive/asset.cpp

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
#include #include < graphene / peerplays_sidechain / ethereum / decoders.hpp>
#include <graphene/peerplays_sidechain/ethereum/decoders.hpp>
namespace graphene { namespace peerplays_sidechain { namespace ethereum {

View file

@ -1,4 +1,4 @@
#include #include < graphene / peerplays_sidechain / ethereum / encoders.hpp>
#include <graphene/peerplays_sidechain/ethereum/encoders.hpp>
namespace graphene { namespace peerplays_sidechain { namespace ethereum {

View file

@ -3,134 +3,31 @@
#include <cstdint>
#include <string>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
//#include <fc/network/http/connection.hpp>
namespace graphene { namespace peerplays_sidechain {
enum class url_schema_type { unknown,
http,
https,
};
// utl
url_schema_type identify_url_schema_type(const std::string &schema_name);
struct url_data {
url_schema_type schema_type;
std::string schema;
std::string host;
uint16_t port;
std::string path;
url_data() :
schema_type(url_schema_type::unknown),
port(0) {
}
url_data(const std::string &url);
void clear();
bool parse(const std::string &url);
};
struct http_request {
struct rpc_reply {
uint16_t status;
std::string body;
std::string content_type;
http_request(const std::string &body_, const std::string &content_type_) :
body(body_),
content_type(content_type_) {
}
};
struct http_response {
uint16_t status_code;
std::string body;
void clear() {
status_code = 0;
body = decltype(body)();
}
};
namespace detail {
template <class>
class http_call_impl;
class tcp_socket;
class ssl_socket;
} // namespace detail
class http_call {
public:
http_call(const url_data &url, const std::string &method = std::string(), const std::string &headers = std::string());
~http_call();
bool is_ssl() const;
const std::string &path() const;
void set_path(const std::string &path);
void set_method(const std::string &method);
void set_headers(const std::string &headers);
const std::string &host() const;
void set_host(const std::string &host);
uint16_t port() const;
void set_port(uint16_t port);
bool exec(const http_request &request, http_response *response);
const std::string &error_what() const;
private:
template <class>
friend class detail::http_call_impl;
friend detail::tcp_socket;
friend detail::ssl_socket;
static constexpr auto response_size_limit_bytes = 16 * 1024 * 1024;
static constexpr auto response_first_alloc_bytes = 32 * 1024;
static constexpr auto response_next_alloc_bytes = 256 * 1024;
std::string m_host;
uint16_t m_port_default;
uint16_t m_port;
std::string m_path;
std::string m_method;
std::string m_headers;
std::string m_error_what;
boost::asio::io_service m_service;
boost::asio::ssl::context *m_context;
boost::asio::ip::tcp::endpoint m_endpoint;
void ctor_priv();
};
}} // namespace graphene::peerplays_sidechain
namespace graphene { namespace peerplays_sidechain {
class rpc_client {
public:
rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug);
rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls);
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);
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;
uint32_t request_id;
private:
http_call client;
http_response send_post_request(const std::string &body, bool show_log);
rpc_reply send_post_request(std::string body, bool show_log);
};
}} // namespace graphene::peerplays_sidechain

View file

@ -1,5 +1,8 @@
#pragma once
#include <string>
#include <vector>
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
}}} // namespace graphene::peerplays_sidechain::ethereum

View file

@ -1,5 +1,8 @@
#pragma once
#include <string>
#include <vector>
namespace graphene { namespace peerplays_sidechain { namespace ethereum {
class ethereum_function_call_encoder {

View file

@ -12,11 +12,12 @@
namespace graphene { namespace peerplays_sidechain {
class ethereum_node_rpc_client : public rpc_client {
class ethereum_rpc_client : public rpc_client {
public:
ethereum_node_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls);
ethereum_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls);
std::string admin_node_info();
std::string eth_get_block_by_number(std::string block_number, bool full_block);
std::string net_version();
std::string get_chain_id();
@ -41,7 +42,7 @@ private:
std::string node_rpc_url;
std::string node_rpc_user;
std::string node_rpc_password;
ethereum_node_rpc_client *node_rpc_client;
ethereum_rpc_client *ethereum_client;
ethereum::chain_id_type chain_id;
ethereum::network_id_type network_id;

View file

@ -159,8 +159,8 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
cli.add_options()("ethereum-sidechain-enabled", bpo::value<bool>()->default_value(false), "Ethereum sidechain handler enabled");
cli.add_options()("ethereum-node-rpc-url", bpo::value<string>()->default_value("127.0.0.1:8545"), "Ethereum node RPC URL [http[s]://]host[:port]");
cli.add_options()("ethereum-node-rpc-user", bpo::value<string>()->default_value("1"), "Ethereum RPC user");
cli.add_options()("ethereum-node-rpc-password", bpo::value<string>()->default_value("1"), "Ethereum RPC password");
cli.add_options()("ethereum-node-rpc-user", bpo::value<string>(), "Ethereum RPC user");
cli.add_options()("ethereum-node-rpc-password", bpo::value<string>(), "Ethereum RPC password");
cli.add_options()("ethereum-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", "9bedac2bd8fe2a6f6528e066c67fc8ac0622e96828d40c0e820d83c5bd2b0589")),
"Tuple of [Ethereum public key, Ethereum private key] (may specify multiple times)");

View file

@ -22,26 +22,31 @@
namespace graphene { namespace peerplays_sidechain {
ethereum_node_rpc_client::ethereum_node_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) :
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) {
}
std::string ethereum_node_rpc_client::admin_node_info() {
std::string ethereum_rpc_client::admin_node_info() {
return send_post_request("admin_nodeInfo", "", debug_rpc_calls);
}
std::string ethereum_node_rpc_client::net_version() {
std::string ethereum_rpc_client::eth_get_block_by_number(std::string block_number, bool full_block) {
std::string params = "[ \"" + block_number + "\", " + (full_block ? "true" : "false") + "]";
return send_post_request("eth_getBlockByNumber", params, debug_rpc_calls);
}
std::string ethereum_rpc_client::net_version() {
return send_post_request("net_version", "", debug_rpc_calls);
}
std::string ethereum_node_rpc_client::get_chain_id() {
std::string ethereum_rpc_client::get_chain_id() {
std::string reply_str = net_version();
return retrieve_value_from_reply(reply_str, "result");
return retrieve_value_from_reply(reply_str, "");
}
std::string ethereum_node_rpc_client::get_network_id() {
std::string ethereum_rpc_client::get_network_id() {
std::string reply_str = admin_node_info();
return retrieve_value_from_reply(reply_str, "result.protocols.eth.network");
return retrieve_value_from_reply(reply_str, "protocols.eth.network");
}
sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
@ -76,15 +81,15 @@ sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidecha
}
}
node_rpc_client = new ethereum_node_rpc_client(node_rpc_url, node_rpc_user, node_rpc_password, debug_rpc_calls);
ethereum_client = new ethereum_rpc_client(node_rpc_url, node_rpc_user, node_rpc_password, debug_rpc_calls);
std::string chain_id_str = node_rpc_client->get_chain_id();
std::string chain_id_str = ethereum_client->get_chain_id();
if (chain_id_str.empty()) {
elog("No Ethereum node running at ${url}", ("url", node_rpc_url));
FC_ASSERT(false);
}
chain_id = std::stoll(chain_id_str);
std::string network_id_str = node_rpc_client->get_network_id();
std::string network_id_str = ethereum_client->get_network_id();
network_id = std::stoll(network_id_str);
ilog("Running on Ethereum network, chain id ${chain_id_str}, network id ${network_id_str}", ("chain_id_str", chain_id_str)("network_id_str", network_id_str));
@ -123,8 +128,6 @@ void sidechain_net_handler_ethereum::process_primary_wallet() {
std::stringstream active_pw_ss(reply_str);
ilog("### process_primary_wallet: ${reply}", ("reply", reply_str));
boost::property_tree::ptree active_pw_pt;
boost::property_tree::read_json(active_pw_ss, active_pw_pt);
if (active_pw_pt.count("error") && active_pw_pt.get_child("error").empty()) {
@ -309,7 +312,7 @@ std::string sidechain_net_handler_ethereum::send_transaction(const sidechain_tra
void sidechain_net_handler_ethereum::schedule_ethereum_listener() {
fc::time_point now = fc::time_point::now();
int64_t time_to_next = 1000;
int64_t time_to_next = 5000;
fc::time_point next_wakeup(now + fc::milliseconds(time_to_next));
@ -321,6 +324,8 @@ void sidechain_net_handler_ethereum::schedule_ethereum_listener() {
void sidechain_net_handler_ethereum::ethereum_listener_loop() {
schedule_ethereum_listener();
std::string reply = ethereum_client->eth_get_block_by_number("latest", true);
}
void sidechain_net_handler_ethereum::handle_event(const std::string &event_data) {