SON listener for Hive
This commit is contained in:
parent
ae712122d4
commit
5920356b5d
10 changed files with 610 additions and 33 deletions
|
|
@ -9,7 +9,8 @@ enum class sidechain_type {
|
|||
bitcoin,
|
||||
ethereum,
|
||||
eos,
|
||||
peerplays
|
||||
peerplays,
|
||||
hive
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
@ -19,4 +20,5 @@ FC_REFLECT_ENUM(graphene::chain::sidechain_type,
|
|||
(bitcoin)
|
||||
(ethereum)
|
||||
(eos)
|
||||
(hive)
|
||||
(peerplays) )
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ add_library( peerplays_sidechain
|
|||
sidechain_net_manager.cpp
|
||||
sidechain_net_handler.cpp
|
||||
sidechain_net_handler_bitcoin.cpp
|
||||
sidechain_net_handler_hive.cpp
|
||||
sidechain_net_handler_peerplays.cpp
|
||||
bitcoin/bech32.cpp
|
||||
bitcoin/bitcoin_address.cpp
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public:
|
|||
boost::program_options::options_description &cfg) override;
|
||||
virtual void plugin_initialize(const boost::program_options::variables_map &options) override;
|
||||
virtual void plugin_startup() override;
|
||||
virtual void plugin_shutdown() override;
|
||||
|
||||
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fc/network/http/connection.hpp>
|
||||
#include <fc/signals.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
class hive_rpc_client {
|
||||
public:
|
||||
hive_rpc_client(std::string _ip, uint32_t _rpc_port, std::string _user, std::string _password);
|
||||
|
||||
std::string block_api_get_block(uint32_t block_number);
|
||||
std::string database_api_get_dynamic_global_properties();
|
||||
|
||||
private:
|
||||
std::string send_post_request(std::string method, std::string params, bool show_log);
|
||||
fc::http::reply send_post_request(std::string body, bool show_log);
|
||||
|
||||
std::string ip;
|
||||
uint32_t rpc_port;
|
||||
std::string user;
|
||||
std::string password;
|
||||
|
||||
fc::http::header authorization;
|
||||
};
|
||||
|
||||
class sidechain_net_handler_hive : public sidechain_net_handler {
|
||||
public:
|
||||
sidechain_net_handler_hive(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options);
|
||||
virtual ~sidechain_net_handler_hive();
|
||||
|
||||
bool process_proposal(const proposal_object &po);
|
||||
void process_primary_wallet();
|
||||
void process_sidechain_addresses();
|
||||
bool process_deposit(const son_wallet_deposit_object &swdo);
|
||||
bool process_withdrawal(const son_wallet_withdraw_object &swwo);
|
||||
std::string process_sidechain_transaction(const sidechain_transaction_object &sto);
|
||||
std::string send_sidechain_transaction(const sidechain_transaction_object &sto);
|
||||
int64_t settle_sidechain_transaction(const sidechain_transaction_object &sto);
|
||||
|
||||
private:
|
||||
std::string ip;
|
||||
uint32_t rpc_port;
|
||||
std::string rpc_user;
|
||||
std::string rpc_password;
|
||||
|
||||
hive_rpc_client *rpc_client;
|
||||
|
||||
uint64_t last_block_received;
|
||||
fc::future<void> _listener_task;
|
||||
fc::signal<void(const std::string &)> event_received;
|
||||
void schedule_hive_listener();
|
||||
void hive_listener_loop();
|
||||
void handle_event(const std::string &event_data);
|
||||
|
||||
void on_applied_block(const signed_block &b);
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -29,6 +29,7 @@ public:
|
|||
boost::program_options::options_description &cfg);
|
||||
void plugin_initialize(const boost::program_options::variables_map &opt);
|
||||
void plugin_startup();
|
||||
void plugin_shutdown();
|
||||
|
||||
std::set<chain::son_id_type> &get_sons();
|
||||
const son_id_type get_current_son_id();
|
||||
|
|
@ -66,8 +67,15 @@ private:
|
|||
|
||||
bool config_ready_son;
|
||||
bool config_ready_bitcoin;
|
||||
bool config_ready_ethereum;
|
||||
bool config_ready_hive;
|
||||
bool config_ready_peerplays;
|
||||
|
||||
bool sidechain_enabled_bitcoin;
|
||||
bool sidechain_enabled_ethereum;
|
||||
bool sidechain_enabled_hive;
|
||||
bool sidechain_enabled_peerplays;
|
||||
|
||||
son_id_type current_son_id;
|
||||
|
||||
std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager;
|
||||
|
|
@ -84,7 +92,13 @@ peerplays_sidechain_plugin_impl::peerplays_sidechain_plugin_impl(peerplays_sidec
|
|||
plugin(_plugin),
|
||||
config_ready_son(false),
|
||||
config_ready_bitcoin(false),
|
||||
config_ready_ethereum(false),
|
||||
config_ready_hive(false),
|
||||
config_ready_peerplays(false),
|
||||
sidechain_enabled_bitcoin(false),
|
||||
sidechain_enabled_ethereum(false),
|
||||
sidechain_enabled_hive(false),
|
||||
sidechain_enabled_peerplays(false),
|
||||
current_son_id(son_id_type(std::numeric_limits<uint32_t>().max())),
|
||||
net_manager(nullptr),
|
||||
first_block_skipped(false) {
|
||||
|
|
@ -121,6 +135,8 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
cli.add_options()("son-ids", bpo::value<string>(), ("IDs of multiple SONs controlled by this node (e.g. [" + son_id_example + ", " + son_id_example2 + "], quotes are required)").c_str());
|
||||
cli.add_options()("peerplays-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
|
||||
"Tuple of [PublicKey, WIF private key] (may specify multiple times)");
|
||||
|
||||
cli.add_options()("bitcoin-sidechain-enabled", bpo::value<bool>()->default_value(false), "Bitcoin sidechain handler enabled");
|
||||
cli.add_options()("bitcoin-node-ip", bpo::value<string>()->default_value("127.0.0.1"), "IP address of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-zmq-port", bpo::value<uint32_t>()->default_value(11111), "ZMQ port of Bitcoin node");
|
||||
cli.add_options()("bitcoin-node-rpc-port", bpo::value<uint32_t>()->default_value(8332), "RPC port of Bitcoin node");
|
||||
|
|
@ -130,6 +146,15 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
cli.add_options()("bitcoin-wallet-password", bpo::value<string>(), "Bitcoin wallet password");
|
||||
cli.add_options()("bitcoin-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("02d0f137e717fb3aab7aff99904001d49a0a636c5e1342f8927a4ba2eaee8e9772", "cVN31uC9sTEr392DLVUEjrtMgLA8Yb3fpYmTRj7bomTm6nn2ANPr")),
|
||||
"Tuple of [Bitcoin public key, Bitcoin 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-ip", bpo::value<string>()->default_value("127.0.0.1"), "IP address of Hive node");
|
||||
cli.add_options()("hive-node-rpc-port", bpo::value<uint32_t>()->default_value(28090), "RPC port of Hive node");
|
||||
cli.add_options()("hive-node-rpc-user", bpo::value<string>(), "Hive RPC user");
|
||||
cli.add_options()("hive-node-rpc-password", bpo::value<string>(), "Hive RPC password");
|
||||
cli.add_options()("hive-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4", "5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n")),
|
||||
"Tuple of [Hive public key, Hive private key] (may specify multiple times)");
|
||||
|
||||
cfg.add(cli);
|
||||
}
|
||||
|
||||
|
|
@ -175,27 +200,48 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
|
|||
throw;
|
||||
}
|
||||
|
||||
sidechain_enabled_bitcoin = options.at("bitcoin-sidechain-enabled").as<bool>();
|
||||
config_ready_bitcoin = options.count("bitcoin-node-ip") &&
|
||||
options.count("bitcoin-node-zmq-port") && options.count("bitcoin-node-rpc-port") &&
|
||||
options.count("bitcoin-node-rpc-user") && options.count("bitcoin-node-rpc-password") &&
|
||||
/*options.count( "bitcoin-wallet" ) && options.count( "bitcoin-wallet-password" ) &&*/
|
||||
/*options.count("bitcoin-wallet") && options.count("bitcoin-wallet-password") &&*/
|
||||
options.count("bitcoin-private-key");
|
||||
if (!config_ready_bitcoin) {
|
||||
wlog("Haven't set up Bitcoin sidechain parameters");
|
||||
}
|
||||
|
||||
//config_ready_ethereum = options.count( "ethereum-node-ip" ) &&
|
||||
// options.count( "ethereum-address" ) && options.count( "ethereum-public-key" ) && options.count( "ethereum-private-key" );
|
||||
//sidechain_enabled_ethereum = options.at("ethereum-sidechain-enabled").as<bool>();
|
||||
//config_ready_ethereum = options.count("ethereum-node-ip") &&
|
||||
// options.count("ethereum-address") &&
|
||||
// options.count("ethereum-public-key") && options.count("ethereum-private-key");
|
||||
//if (!config_ready_ethereum) {
|
||||
// wlog("Haven't set up Ethereum sidechain parameters");
|
||||
//}
|
||||
|
||||
sidechain_enabled_hive = options.at("hive-sidechain-enabled").as<bool>();
|
||||
config_ready_hive = options.count("hive-node-ip") &&
|
||||
options.count("hive-node-rpc-port") &&
|
||||
/*options.count("hive-node-rpc-user") && options.count("bitcoin-node-rpc-password") &&*/
|
||||
/*options.count("hive-wallet") && options.count("hive-wallet-password") &&*/
|
||||
options.count("hive-private-key");
|
||||
if (!config_ready_hive) {
|
||||
wlog("Haven't set up Hive sidechain parameters");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS
|
||||
sidechain_enabled_peerplays = true; //options.at("peerplays-sidechain-enabled").as<bool>();
|
||||
#else
|
||||
sidechain_enabled_peerplays = false;
|
||||
#endif
|
||||
config_ready_peerplays = true;
|
||||
if (!config_ready_peerplays) {
|
||||
wlog("Haven't set up Peerplays sidechain parameters");
|
||||
}
|
||||
|
||||
if (!(config_ready_bitcoin /*&& config_ready_ethereum*/ && config_ready_peerplays)) {
|
||||
if (!(config_ready_bitcoin &&
|
||||
/*config_ready_ethereum &&*/
|
||||
config_ready_hive &&
|
||||
config_ready_peerplays)) {
|
||||
wlog("Haven't set up any sidechain parameters");
|
||||
throw;
|
||||
}
|
||||
|
|
@ -213,17 +259,22 @@ void peerplays_sidechain_plugin_impl::plugin_startup() {
|
|||
|
||||
net_manager = std::unique_ptr<sidechain_net_manager>(new sidechain_net_manager(plugin));
|
||||
|
||||
if (config_ready_bitcoin) {
|
||||
if (sidechain_enabled_bitcoin && config_ready_bitcoin) {
|
||||
net_manager->create_handler(sidechain_type::bitcoin, options);
|
||||
ilog("Bitcoin sidechain handler running");
|
||||
}
|
||||
|
||||
//if (config_ready_ethereum) {
|
||||
//if (sidechain_enabled_ethereum && config_ready_ethereum) {
|
||||
// net_manager->create_handler(sidechain_type::ethereum, options);
|
||||
// ilog("Ethereum sidechain handler running");
|
||||
//}
|
||||
|
||||
if (config_ready_peerplays) {
|
||||
if (sidechain_enabled_hive && config_ready_hive) {
|
||||
net_manager->create_handler(sidechain_type::hive, options);
|
||||
ilog("Hive sidechain handler running");
|
||||
}
|
||||
|
||||
if (sidechain_enabled_peerplays && config_ready_peerplays) {
|
||||
net_manager->create_handler(sidechain_type::peerplays, options);
|
||||
ilog("Peerplays sidechain handler running");
|
||||
}
|
||||
|
|
@ -233,6 +284,9 @@ void peerplays_sidechain_plugin_impl::plugin_startup() {
|
|||
});
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::plugin_shutdown() {
|
||||
}
|
||||
|
||||
std::set<chain::son_id_type> &peerplays_sidechain_plugin_impl::get_sons() {
|
||||
return sons;
|
||||
}
|
||||
|
|
@ -279,7 +333,7 @@ bool peerplays_sidechain_plugin_impl::is_son_deregistered(son_id_type son_id) {
|
|||
if (son_obj == idx.end())
|
||||
return true;
|
||||
|
||||
if(son_obj->status == chain::son_status::deregistered) {
|
||||
if (son_obj->status == chain::son_status::deregistered) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -663,6 +717,12 @@ void peerplays_sidechain_plugin::plugin_startup() {
|
|||
ilog("peerplays sidechain plugin: plugin_startup() end");
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_shutdown() {
|
||||
ilog("peerplays sidechain plugin: plugin_shutdown() begin");
|
||||
my->plugin_shutdown();
|
||||
ilog("peerplays sidechain plugin: plugin_shutdown() end");
|
||||
}
|
||||
|
||||
std::set<chain::son_id_type> &peerplays_sidechain_plugin::get_sons() {
|
||||
return my->get_sons();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ void sidechain_net_handler::process_proposals() {
|
|||
|
||||
int32_t op_idx_1 = -1;
|
||||
chain::operation op_obj_idx_1;
|
||||
(void) op_idx_1;
|
||||
(void)op_idx_1;
|
||||
|
||||
if (po->proposed_transaction.operations.size() >= 2) {
|
||||
op_idx_1 = po->proposed_transaction.operations[1].which();
|
||||
|
|
|
|||
|
|
@ -1005,7 +1005,7 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
|
|||
|
||||
int32_t op_idx_1 = -1;
|
||||
chain::operation op_obj_idx_1;
|
||||
(void) op_idx_1;
|
||||
(void)op_idx_1;
|
||||
|
||||
if (po.proposed_transaction.operations.size() >= 2) {
|
||||
op_idx_1 = po.proposed_transaction.operations[1].which();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,443 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include <fc/crypto/base64.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <graphene/chain/protocol/son_wallet.hpp>
|
||||
#include <graphene/chain/son_info.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/utilities/key_conversion.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
hive_rpc_client::hive_rpc_client(std::string _ip, uint32_t _rpc_port, std::string _user, std::string _password) :
|
||||
ip(_ip),
|
||||
rpc_port(_rpc_port),
|
||||
user(_user),
|
||||
password(_password) {
|
||||
authorization.key = "Authorization";
|
||||
authorization.val = "Basic " + fc::base64_encode(user + ":" + password);
|
||||
}
|
||||
|
||||
std::string hive_rpc_client::block_api_get_block(uint32_t block_number) {
|
||||
std::string params = "{ \"block_num\": " + std::to_string(block_number) + " }";
|
||||
return send_post_request("block_api.get_block", params, true);
|
||||
}
|
||||
|
||||
std::string hive_rpc_client::database_api_get_dynamic_global_properties() {
|
||||
return send_post_request("database_api.get_dynamic_global_properties", "", false);
|
||||
}
|
||||
|
||||
std::string hive_rpc_client::send_post_request(std::string method, std::string params, bool show_log) {
|
||||
std::stringstream body;
|
||||
|
||||
body << "{ \"jsonrpc\": \"2.0\", \"id\": \"" << method << "\", \"method\": \"" << method << "\"";
|
||||
|
||||
if (!params.empty()) {
|
||||
body << ", \"params\": " << params << "}";
|
||||
}
|
||||
|
||||
body << " }";
|
||||
|
||||
const auto reply = send_post_request(body.str(), show_log);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
wlog("Hive RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
|
||||
if (reply.status == 200) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
if (json.count("error") && !json.get_child("error").empty()) {
|
||||
wlog("Hive RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body.str())("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
fc::http::reply hive_rpc_client::send_post_request(std::string body, bool show_log) {
|
||||
fc::http::connection conn;
|
||||
conn.connect_to(fc::ip::endpoint(fc::ip::address(ip), rpc_port));
|
||||
|
||||
std::string url = "http://" + ip + ":" + std::to_string(rpc_port);
|
||||
|
||||
//if (wallet.length() > 0) {
|
||||
// url = url + "/wallet/" + wallet;
|
||||
//}
|
||||
|
||||
fc::http::reply reply = conn.request("POST", url, body, fc::http::headers{authorization});
|
||||
|
||||
if (show_log) {
|
||||
ilog("### Request URL: ${url}", ("url", url));
|
||||
ilog("### Request: ${body}", ("body", body));
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
ilog("### Response: ${ss}", ("ss", ss.str()));
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ip = options.at("hive-node-ip").as<std::string>();
|
||||
rpc_port = options.at("hive-node-rpc-port").as<uint32_t>();
|
||||
if (options.count("hive-node-rpc-user")) {
|
||||
rpc_user = options.at("hive-node-rpc-user").as<std::string>();
|
||||
} else {
|
||||
rpc_user = "";
|
||||
}
|
||||
if (options.count("hive-node-rpc-password")) {
|
||||
rpc_password = options.at("hive-node-rpc-password").as<std::string>();
|
||||
} else {
|
||||
rpc_password = "";
|
||||
}
|
||||
|
||||
if (options.count("hive-private-key")) {
|
||||
const std::vector<std::string> pub_priv_keys = options["hive-private-key"].as<std::vector<std::string>>();
|
||||
for (const std::string &itr_key_pair : pub_priv_keys) {
|
||||
auto key_pair = graphene::app::dejsonify<std::pair<std::string, std::string>>(itr_key_pair, 5);
|
||||
ilog("Hive Public Key: ${public}", ("public", key_pair.first));
|
||||
if (!key_pair.first.length() || !key_pair.second.length()) {
|
||||
FC_THROW("Invalid public private key pair.");
|
||||
}
|
||||
private_keys[key_pair.first] = key_pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
fc::http::connection conn;
|
||||
try {
|
||||
conn.connect_to(fc::ip::endpoint(fc::ip::address(ip), rpc_port));
|
||||
} catch (fc::exception &e) {
|
||||
elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", ip)("port", rpc_port));
|
||||
FC_ASSERT(false);
|
||||
}
|
||||
|
||||
rpc_client = new hive_rpc_client(ip, rpc_port, rpc_user, rpc_password);
|
||||
|
||||
last_block_received = 0;
|
||||
schedule_hive_listener();
|
||||
event_received.connect([this](const std::string &event_data) {
|
||||
std::thread(&sidechain_net_handler_hive::handle_event, this, event_data).detach();
|
||||
});
|
||||
}
|
||||
|
||||
sidechain_net_handler_hive::~sidechain_net_handler_hive() {
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) {
|
||||
|
||||
ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id()));
|
||||
|
||||
bool should_approve = false;
|
||||
|
||||
// const chain::global_property_object &gpo = database.get_global_properties();
|
||||
//
|
||||
// int32_t op_idx_0 = -1;
|
||||
// chain::operation op_obj_idx_0;
|
||||
//
|
||||
// if (po.proposed_transaction.operations.size() >= 1) {
|
||||
// op_idx_0 = po.proposed_transaction.operations[0].which();
|
||||
// op_obj_idx_0 = po.proposed_transaction.operations[0];
|
||||
// }
|
||||
//
|
||||
// switch (op_idx_0) {
|
||||
//
|
||||
// case chain::operation::tag<chain::son_wallet_update_operation>::value: {
|
||||
// should_approve = false;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// case chain::operation::tag<chain::son_wallet_deposit_process_operation>::value: {
|
||||
// son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get<son_wallet_deposit_process_operation>().son_wallet_deposit_id;
|
||||
// const auto &idx = database.get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
|
||||
// const auto swdo = idx.find(swdo_id);
|
||||
// if (swdo != idx.end()) {
|
||||
//
|
||||
// uint32_t swdo_block_num = swdo->block_num;
|
||||
// std::string swdo_sidechain_transaction_id = swdo->sidechain_transaction_id;
|
||||
// uint32_t swdo_op_idx = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1));
|
||||
//
|
||||
// const auto &block = database.fetch_block_by_number(swdo_block_num);
|
||||
//
|
||||
// for (const auto &tx : block->transactions) {
|
||||
// if (tx.id().str() == swdo_sidechain_transaction_id) {
|
||||
// operation op = tx.operations[swdo_op_idx];
|
||||
// transfer_operation t_op = op.get<transfer_operation>();
|
||||
//
|
||||
// asset sidechain_asset = asset(swdo->sidechain_amount, fc::variant(swdo->sidechain_currency, 1).as<asset_id_type>(1));
|
||||
// price sidechain_asset_price = database.get<asset_object>(sidechain_asset.asset_id).options.core_exchange_rate;
|
||||
// asset peerplays_asset = asset(sidechain_asset.amount * sidechain_asset_price.base.amount / sidechain_asset_price.quote.amount);
|
||||
//
|
||||
// should_approve = (gpo.parameters.son_account() == t_op.to) &&
|
||||
// (swdo->peerplays_from == t_op.from) &&
|
||||
// (sidechain_asset == t_op.amount) &&
|
||||
// (swdo->peerplays_asset == peerplays_asset);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// case chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value: {
|
||||
// should_approve = false;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// case chain::operation::tag<chain::sidechain_transaction_settle_operation>::value: {
|
||||
// should_approve = true;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// default:
|
||||
// should_approve = false;
|
||||
// elog("==================================================");
|
||||
// elog("Proposal not considered for approval ${po}", ("po", po));
|
||||
// elog("==================================================");
|
||||
// }
|
||||
|
||||
return should_approve;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::process_primary_wallet() {
|
||||
return;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::process_sidechain_addresses() {
|
||||
// const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>();
|
||||
// const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
|
||||
// const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
|
||||
// std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
|
||||
// [&](const sidechain_address_object &sao) {
|
||||
// bool retval = true;
|
||||
// if (sao.expires == time_point_sec::maximum()) {
|
||||
// if (sao.deposit_address == "") {
|
||||
// sidechain_address_update_operation op;
|
||||
// op.payer = plugin.get_current_son_object().son_account;
|
||||
// op.sidechain_address_id = sao.id;
|
||||
// op.sidechain_address_account = sao.sidechain_address_account;
|
||||
// op.sidechain = sao.sidechain;
|
||||
// op.deposit_public_key = sao.deposit_public_key;
|
||||
// op.deposit_address = sao.withdraw_address;
|
||||
// op.deposit_address_data = sao.withdraw_address;
|
||||
// op.withdraw_public_key = sao.withdraw_public_key;
|
||||
// op.withdraw_address = sao.withdraw_address;
|
||||
//
|
||||
// signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op);
|
||||
// try {
|
||||
// trx.validate();
|
||||
// database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
// if (plugin.app().p2p_node())
|
||||
// plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
// retval = true;
|
||||
// } catch (fc::exception &e) {
|
||||
// elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what()));
|
||||
// retval = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return retval;
|
||||
// });
|
||||
return;
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
|
||||
// const chain::global_property_object &gpo = database.get_global_properties();
|
||||
//
|
||||
// asset_issue_operation ai_op;
|
||||
// ai_op.issuer = gpo.parameters.son_account();
|
||||
// price btc_price = database.get<asset_object>(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate;
|
||||
// ai_op.asset_to_issue = asset(swdo.peerplays_asset.amount * btc_price.quote.amount / btc_price.base.amount, database.get_global_properties().parameters.btc_asset());
|
||||
// ai_op.issue_to_account = swdo.peerplays_from;
|
||||
//
|
||||
// signed_transaction tx;
|
||||
// auto dyn_props = database.get_dynamic_global_properties();
|
||||
// tx.set_reference_block(dyn_props.head_block_id);
|
||||
// tx.set_expiration(database.head_block_time() + gpo.parameters.maximum_time_until_expiration);
|
||||
// tx.operations.push_back(ai_op);
|
||||
// database.current_fee_schedule().set_fee(tx.operations.back());
|
||||
//
|
||||
// std::stringstream ss;
|
||||
// fc::raw::pack(ss, tx, 1000);
|
||||
// std::string tx_str = boost::algorithm::hex(ss.str());
|
||||
//
|
||||
// if (!tx_str.empty()) {
|
||||
// const chain::global_property_object &gpo = database.get_global_properties();
|
||||
//
|
||||
// sidechain_transaction_create_operation stc_op;
|
||||
// stc_op.payer = gpo.parameters.son_account();
|
||||
// stc_op.object_id = swdo.id;
|
||||
// stc_op.sidechain = sidechain;
|
||||
// stc_op.transaction = tx_str;
|
||||
// stc_op.signers = gpo.active_sons;
|
||||
//
|
||||
// proposal_create_operation proposal_op;
|
||||
// proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
// proposal_op.proposed_ops.emplace_back(stc_op);
|
||||
// uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
// proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
//
|
||||
// signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
// try {
|
||||
// trx.validate();
|
||||
// database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
// if (plugin.app().p2p_node())
|
||||
// plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
// return true;
|
||||
// } catch (fc::exception &e) {
|
||||
// elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_hive::process_sidechain_transaction(const sidechain_transaction_object &sto) {
|
||||
|
||||
// std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction));
|
||||
// signed_transaction trx;
|
||||
// fc::raw::unpack(ss_trx, trx, 1000);
|
||||
//
|
||||
// fc::optional<fc::ecc::private_key> privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain)));
|
||||
// signature_type st = trx.sign(*privkey, database.get_chain_id());
|
||||
//
|
||||
std::stringstream ss_st;
|
||||
// fc::raw::pack(ss_st, st, 1000);
|
||||
std::string st_str = boost::algorithm::hex(ss_st.str());
|
||||
|
||||
return st_str;
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidechain_transaction_object &sto) {
|
||||
|
||||
// std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction));
|
||||
// signed_transaction trx;
|
||||
// fc::raw::unpack(ss_trx, trx, 1000);
|
||||
//
|
||||
// for (auto signature : sto.signatures) {
|
||||
// if (!signature.second.empty()) {
|
||||
// std::stringstream ss_st(boost::algorithm::unhex(signature.second));
|
||||
// signature_type st;
|
||||
// fc::raw::unpack(ss_st, st, 1000);
|
||||
//
|
||||
// trx.signatures.push_back(st);
|
||||
// trx.signees.clear();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// trx.validate();
|
||||
// database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
// if (plugin.app().p2p_node())
|
||||
// plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
// return trx.id().str();
|
||||
// } catch (fc::exception &e) {
|
||||
// elog("Sidechain transaction failed with exception ${e}", ("e", e.what()));
|
||||
// return "";
|
||||
// }
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int64_t sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_transaction_object &sto) {
|
||||
int64_t settle_amount = 0;
|
||||
return settle_amount;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::schedule_hive_listener() {
|
||||
fc::time_point now = fc::time_point::now();
|
||||
int64_t time_to_next = 1000;
|
||||
|
||||
fc::time_point next_wakeup(now + fc::milliseconds(time_to_next));
|
||||
|
||||
_listener_task = fc::schedule([this] {
|
||||
hive_listener_loop();
|
||||
},
|
||||
next_wakeup, "SON Hive listener task");
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::hive_listener_loop() {
|
||||
schedule_hive_listener();
|
||||
|
||||
std::string reply = rpc_client->database_api_get_dynamic_global_properties();
|
||||
|
||||
if (!reply.empty()) {
|
||||
std::stringstream ss(reply);
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
if (json.count("result")) {
|
||||
uint64_t head_block_number = json.get<uint64_t>("result.head_block_number");
|
||||
if (head_block_number != last_block_received) {
|
||||
std::string event_data = std::to_string(head_block_number);
|
||||
handle_event(event_data);
|
||||
last_block_received = head_block_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
|
||||
std::string block = rpc_client->block_api_get_block(std::atoll(event_data.c_str()));
|
||||
}
|
||||
|
||||
void sidechain_net_handler_hive::on_applied_block(const signed_block &b) {
|
||||
// for (const auto &trx : b.transactions) {
|
||||
// size_t operation_index = -1;
|
||||
// for (auto op : trx.operations) {
|
||||
// operation_index = operation_index + 1;
|
||||
// if (op.which() == operation::tag<transfer_operation>::value) {
|
||||
// transfer_operation transfer_op = op.get<transfer_operation>();
|
||||
// if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// std::stringstream ss;
|
||||
// ss << "peerplays"
|
||||
// << "-" << trx.id().str() << "-" << operation_index;
|
||||
// std::string sidechain_uid = ss.str();
|
||||
//
|
||||
// sidechain_event_data sed;
|
||||
// sed.timestamp = database.head_block_time();
|
||||
// sed.block_num = database.head_block_num();
|
||||
// sed.sidechain = sidechain_type::peerplays;
|
||||
// sed.sidechain_uid = sidechain_uid;
|
||||
// sed.sidechain_transaction_id = trx.id().str();
|
||||
// sed.sidechain_from = fc::to_string(transfer_op.from.space_id) + "." + fc::to_string(transfer_op.from.type_id) + "." + fc::to_string((uint64_t)transfer_op.from.instance);
|
||||
// sed.sidechain_to = fc::to_string(transfer_op.to.space_id) + "." + fc::to_string(transfer_op.to.type_id) + "." + fc::to_string((uint64_t)transfer_op.to.instance);
|
||||
// sed.sidechain_currency = fc::to_string(transfer_op.amount.asset_id.space_id) + "." + fc::to_string(transfer_op.amount.asset_id.type_id) + "." + fc::to_string((uint64_t)transfer_op.amount.asset_id.instance);
|
||||
// sed.sidechain_amount = transfer_op.amount.amount;
|
||||
// sed.peerplays_from = transfer_op.from;
|
||||
// sed.peerplays_to = transfer_op.to;
|
||||
// price asset_price = database.get<asset_object>(transfer_op.amount.asset_id).options.core_exchange_rate;
|
||||
// sed.peerplays_asset = asset(transfer_op.amount.amount * asset_price.base.amount / asset_price.quote.amount);
|
||||
// sidechain_event_data_received(sed);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -131,34 +131,34 @@ void sidechain_net_handler_peerplays::process_sidechain_addresses() {
|
|||
const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
|
||||
std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
|
||||
[&](const sidechain_address_object &sao) {
|
||||
bool retval = true;
|
||||
bool retval = true;
|
||||
if (sao.expires == time_point_sec::maximum()) {
|
||||
if (sao.deposit_address == "") {
|
||||
sidechain_address_update_operation op;
|
||||
op.payer = plugin.get_current_son_object().son_account;
|
||||
op.sidechain_address_id = sao.id;
|
||||
op.sidechain_address_account = sao.sidechain_address_account;
|
||||
op.sidechain = sao.sidechain;
|
||||
op.deposit_public_key = sao.deposit_public_key;
|
||||
op.deposit_address = sao.withdraw_address;
|
||||
op.deposit_address_data = sao.withdraw_address;
|
||||
op.withdraw_public_key = sao.withdraw_public_key;
|
||||
op.withdraw_address = sao.withdraw_address;
|
||||
op.payer = plugin.get_current_son_object().son_account;
|
||||
op.sidechain_address_id = sao.id;
|
||||
op.sidechain_address_account = sao.sidechain_address_account;
|
||||
op.sidechain = sao.sidechain;
|
||||
op.deposit_public_key = sao.deposit_public_key;
|
||||
op.deposit_address = sao.withdraw_address;
|
||||
op.deposit_address_data = sao.withdraw_address;
|
||||
op.withdraw_public_key = sao.withdraw_public_key;
|
||||
op.withdraw_address = sao.withdraw_address;
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
retval = true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what()));
|
||||
retval = false;
|
||||
}
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
retval = true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what()));
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
return retval;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <fc/log/logger.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
|
@ -26,6 +27,12 @@ bool sidechain_net_manager::create_handler(sidechain_type sidechain, const boost
|
|||
ret_val = true;
|
||||
break;
|
||||
}
|
||||
case sidechain_type::hive: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_hive(plugin, options));
|
||||
net_handlers.push_back(std::move(h));
|
||||
ret_val = true;
|
||||
break;
|
||||
}
|
||||
case sidechain_type::peerplays: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_peerplays(plugin, options));
|
||||
net_handlers.push_back(std::move(h));
|
||||
|
|
|
|||
Loading…
Reference in a new issue