From 5920356b5dbbd5b60a172fb6a189924a3e08d622 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Fri, 5 Mar 2021 16:24:09 +0100 Subject: [PATCH 01/57] SON listener for Hive --- .../include/graphene/chain/sidechain_defs.hpp | 4 +- .../peerplays_sidechain/CMakeLists.txt | 1 + .../peerplays_sidechain_plugin.hpp | 1 + .../sidechain_net_handler_hive.hpp | 63 +++ .../peerplays_sidechain_plugin.cpp | 76 ++- .../sidechain_net_handler.cpp | 2 +- .../sidechain_net_handler_bitcoin.cpp | 2 +- .../sidechain_net_handler_hive.cpp | 443 ++++++++++++++++++ .../sidechain_net_handler_peerplays.cpp | 44 +- .../sidechain_net_manager.cpp | 7 + 10 files changed, 610 insertions(+), 33 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp create mode 100644 libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp diff --git a/libraries/chain/include/graphene/chain/sidechain_defs.hpp b/libraries/chain/include/graphene/chain/sidechain_defs.hpp index 6bbc8b5c..7f986f96 100644 --- a/libraries/chain/include/graphene/chain/sidechain_defs.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_defs.hpp @@ -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) ) diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 3737ae61..f7104af9 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -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 diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp index 80086c10..437134c0 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp @@ -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 my; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp new file mode 100644 index 00000000..c9c8fe95 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include + +#include +#include + +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 _listener_task; + fc::signal 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 diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index abde7b51..40836cb6 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -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 &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 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().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(), ("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>()->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()->default_value(false), "Bitcoin sidechain handler enabled"); cli.add_options()("bitcoin-node-ip", bpo::value()->default_value("127.0.0.1"), "IP address of Bitcoin node"); cli.add_options()("bitcoin-node-zmq-port", bpo::value()->default_value(11111), "ZMQ port of Bitcoin node"); cli.add_options()("bitcoin-node-rpc-port", bpo::value()->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(), "Bitcoin wallet password"); cli.add_options()("bitcoin-private-key", bpo::value>()->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()->default_value(false), "Hive sidechain handler enabled"); + cli.add_options()("hive-node-ip", bpo::value()->default_value("127.0.0.1"), "IP address of Hive node"); + cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "RPC port of Hive node"); + cli.add_options()("hive-node-rpc-user", bpo::value(), "Hive RPC user"); + cli.add_options()("hive-node-rpc-password", bpo::value(), "Hive RPC password"); + cli.add_options()("hive-private-key", bpo::value>()->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(); 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(); + //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(); + 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(); +#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(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 &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 &peerplays_sidechain_plugin::get_sons() { return my->get_sons(); } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 5ceab83a..28c44397 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -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(); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 65b00b19..2cf8b68a 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -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(); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp new file mode 100644 index 00000000..dbdc331a --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -0,0 +1,443 @@ +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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(); + rpc_port = options.at("hive-node-rpc-port").as(); + if (options.count("hive-node-rpc-user")) { + rpc_user = options.at("hive-node-rpc-user").as(); + } else { + rpc_user = ""; + } + if (options.count("hive-node-rpc-password")) { + rpc_password = options.at("hive-node-rpc-password").as(); + } else { + rpc_password = ""; + } + + if (options.count("hive-private-key")) { + const std::vector pub_priv_keys = options["hive-private-key"].as>(); + for (const std::string &itr_key_pair : pub_priv_keys) { + auto key_pair = graphene::app::dejsonify>(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::value: { + // should_approve = false; + // break; + // } + // + // case chain::operation::tag::value: { + // son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + // const auto &idx = database.get_index_type().indices().get(); + // 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(); + // + // asset sidechain_asset = asset(swdo->sidechain_amount, fc::variant(swdo->sidechain_currency, 1).as(1)); + // price sidechain_asset_price = database.get(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::value: { + // should_approve = false; + // break; + // } + // + // case chain::operation::tag::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(); + // const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get(); + // 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(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 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("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::value) { + // transfer_operation transfer_op = op.get(); + // 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(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 diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 1bbce500..5e481410 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -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; } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 962488a6..4fa792b4 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include 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 h = std::unique_ptr(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 h = std::unique_ptr(new sidechain_net_handler_peerplays(plugin, options)); net_handlers.push_back(std::move(h)); -- 2.45.2 From 8e4ff85c901482b4bd95a55a1541ad1a79aea157 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Fri, 12 Mar 2021 20:10:44 +0100 Subject: [PATCH 02/57] Hive block basic parsing --- .../bitcoin/bitcoin_script.cpp | 2 +- .../sidechain_net_handler_hive.cpp | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp b/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp index 2e71adb5..50c02964 100644 --- a/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include namespace graphene { namespace peerplays_sidechain { namespace bitcoin { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index dbdc331a..053ab857 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -402,6 +402,79 @@ void sidechain_net_handler_hive::hive_listener_loop() { 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())); + if (block != "") { + std::stringstream ss(block); + boost::property_tree::ptree block_json; + boost::property_tree::read_json(ss, block_json); + + for (const auto &tx_child : block_json.get_child("result.block.transactions")) { + const auto &tx = tx_child.second; + + for (const auto &ops : tx.get_child("operations")) { + const auto &op = ops.second; + + std::string operation_type = op.get("type"); + ilog("Transactions: ${operation_type}", ("operation_type", operation_type)); + + if (operation_type == "transfer_operation") { + const auto &op_value = op.get_child("value"); + + std::string from = op_value.get("from"); + std::string to = op_value.get("to"); + + const auto &amount_child = op_value.get_child("amount"); + + uint64_t amount = amount_child.get("amount"); + uint64_t precision = amount_child.get("precision"); + std::string nai = amount_child.get("nai"); + + ilog("Transfer from ${from} to ${to}, amount ${amount}, precision ${precision}, nai ${nai}", + ("from", from)("to", to)("amount", amount)("precision", precision)("nai", nai)); + } + } + } + + boost::property_tree::ptree transactions_json = block_json.get_child("result.block.transactions"); + ss.str(""); + boost::property_tree::write_json(ss, transactions_json); + elog("Transactions: ${ss}", ("ss", ss.str())); + + //{"jsonrpc":"2.0","result":{"block":{"previous":"00006dd6c2b98bc7d1214f61f1c797bb22edb4cd","timestamp":"2021-03-10T12:18:21","witness":"initminer","transaction_merkle_root":"55d89a7b615a4d25f32d9160ce6714a5de5f2b05","extensions":[],"witness_signature":"1f0e2115cb18d862a279de93f3d4d82df4210984e26231db206de8b37e26b2aa8048f21fc7447f842047fea7ffa2a481eede07d379bf9577ab09b5395434508d86","transactions":[{"ref_block_num":28118,"ref_block_prefix":3347823042,"expiration":"2021-03-10T12:18:48","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f55c34b9fab328de76d7c4afd30ca1b64742f46d2aee759b66fc9b0e9d90653a44dbad1ef583c9578666abc23db0ca540f32746d7ac4ff7a6394d28a2c9ef29f3"]}],"block_id":"00006dd7a264f6a8d833ad88a7eeb3abdd483af3","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["73eb9d7a19b9bcb941500f4a9924c13fe3b94c4a"]}},"id":"block_api.get_block"} + //{"jsonrpc":"2.0","result":{"block":{"previous":"00006de5714685397129f52693504ed3abde8e44","timestamp":"2021-03-10T12:19:06","witness":"initminer","transaction_merkle_root":"8b9bcb4b0aed33624a68abdf2860e76136ae9313","extensions":[],"witness_signature":"20f0743c1c3f63230f8af615e14ca0c5143ddfde0c5cee83c24486276223ceb21e7950f1b503750aad73f979bbdf6a298c9e22a079cc1397ed9d4a6eb8aeccea79","transactions":[{"ref_block_num":28133,"ref_block_prefix":965035633,"expiration":"2021-03-10T12:19:33","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f519b0e13ee672108670540f846ad7cef676c94e3169e2d4c3ff12b5dad6dc412154cb45677b2caa0f839b5e2826ae96d6bbf36987ab40a928c3e0081e10a082e"]}],"block_id":"00006de655bac50cb40e05fc02eaef112ccae454","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["28c09bb777827fbf41023c50600aef65e0c83a8b"]}},"id":"block_api.get_block"} + //{"jsonrpc":"2.0","result":{"block":{"previous":"00006dfe471f2224d4b6c3189c7a2a5ed261c277","timestamp":"2021-03-10T12:20:21","witness":"initminer","transaction_merkle_root":"e407272ab2e383e5fef487651d88e0c0c3617e29","extensions":[],"witness_signature":"1f48152244ad2036e3761248a93a9c38fb8c7ee8a0721f9f47ae267b63808e56c223ab15641ec2baad6be4a54db5df04ead9b7f1107dba267a89c02c49d8115fbf","transactions":[{"ref_block_num":28158,"ref_block_prefix":606216007,"expiration":"2021-03-10T12:20:48","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f5b4c7a8695b6c68b6ee96000367ffa96c23d9f4ed8ca36f639b38351b8198d18626f3b8277ca5c92bd537c68db5f9730f3f9df59a8ce631e9dcf7ce53032796b"]}],"block_id":"00006dff4bcd9a790193924fe44d0bdc3fde1c83","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["50b8f4b268a0fa3a34698dd6f8152117343e6c06"]}},"id":"block_api.get_block"} + + //const auto &vins = extract_info_from_block(block); + + const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); + + /*for (const auto &v : vins) { + // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address, time_point_sec::maximum())); + if (addr_itr == sidechain_addresses_idx.end()) + continue; + + std::stringstream ss; + ss << "bitcoin" + << "-" << v.out.hash_tx << "-" << v.out.n_vout; + 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 = addr_itr->sidechain; + sed.sidechain_uid = sidechain_uid; + sed.sidechain_transaction_id = v.out.hash_tx; + sed.sidechain_from = ""; + sed.sidechain_to = v.address; + sed.sidechain_currency = "BTC"; + sed.sidechain_amount = v.out.amount; + sed.peerplays_from = addr_itr->sidechain_address_account; + sed.peerplays_to = database.get_global_properties().parameters.son_account(); + price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount); + sidechain_event_data_received(sed); + }*/ + } } void sidechain_net_handler_hive::on_applied_block(const signed_block &b) { -- 2.45.2 From 093fdf055a516f6c7032826b16c9acb369b9cf80 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 17 Mar 2021 01:56:44 +0100 Subject: [PATCH 03/57] Hive primary wallet creation --- .../peerplays_sidechain/CMakeLists.txt | 1 + .../peerplays_sidechain/common/rpc_client.cpp | 80 +++++++ .../peerplays_sidechain/common/rpc_client.hpp | 28 +++ .../sidechain_net_handler_hive.hpp | 40 ++-- .../peerplays_sidechain_plugin.cpp | 18 +- .../sidechain_net_handler_hive.cpp | 206 ++++++++++++------ 6 files changed, 279 insertions(+), 94 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/common/rpc_client.cpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index f7104af9..6b5b147e 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -14,6 +14,7 @@ add_library( peerplays_sidechain bitcoin/segwit_addr.cpp bitcoin/utils.cpp bitcoin/sign_bitcoin_transaction.cpp + common/rpc_client.cpp ) if (ENABLE_DEV_FEATURES) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp new file mode 100644 index 00000000..6570f181 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -0,0 +1,80 @@ +#include + +#include + +#include +#include + +#include +#include +#include + +namespace graphene { namespace peerplays_sidechain { + +rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : + ip(_ip), + port(_port), + user(_user), + password(_password), + request_id(0) { + authorization.key = "Authorization"; + authorization.val = "Basic " + fc::base64_encode(user + ":" + password); +} + +std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log) { + std::stringstream body; + + request_id = request_id + 1; + + body << "{ \"jsonrpc\": \"2.0\", \"id\": " << request_id << ", \"method\": \"" << method << "\""; + + if (!params.empty()) { + body << ", \"params\": " << params; + } + + body << " }"; + + const auto reply = send_post_request(body.str(), show_log); + + if (reply.body.empty()) { + wlog("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("RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body.str())("msg", ss.str())); + } + return ""; +} + +fc::http::reply 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), port)); + + std::string url = "http://" + ip + ":" + std::to_string(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; +} + +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp new file mode 100644 index 00000000..04b88361 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include + +namespace graphene { namespace peerplays_sidechain { + +class rpc_client { +public: + rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); + +protected: + 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 port; + std::string user; + std::string password; + + uint32_t request_id; + + fc::http::header authorization; +}; + +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index c9c8fe95..59ce174d 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -7,25 +7,28 @@ #include #include +#include + namespace graphene { namespace peerplays_sidechain { -class hive_rpc_client { +class hive_node_rpc_client : public rpc_client { public: - hive_rpc_client(std::string _ip, uint32_t _rpc_port, std::string _user, std::string _password); + hive_node_rpc_client(std::string _ip, uint32_t _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); +class hive_wallet_rpc_client : public rpc_client { +public: + hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); - std::string ip; - uint32_t rpc_port; - std::string user; - std::string password; - - fc::http::header authorization; + std::string get_account(std::string account); + std::string lock(); + std::string unlock(std::string password); + std::string update_account_auth_key(std::string account_name, std::string type, std::string public_key, std::string weight); + std::string update_account_auth_account(std::string account_name, std::string type, std::string auth_account, std::string weight); + std::string update_account_auth_threshold(std::string account_name, std::string type, std::string threshold); }; class sidechain_net_handler_hive : public sidechain_net_handler { @@ -43,12 +46,17 @@ public: 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; + std::string node_ip; + uint32_t node_rpc_port; + std::string node_rpc_user; + std::string node_rpc_password; + hive_node_rpc_client *node_rpc_client; - hive_rpc_client *rpc_client; + std::string wallet_ip; + uint32_t wallet_rpc_port; + std::string wallet_rpc_user; + std::string wallet_rpc_password; + hive_wallet_rpc_client *wallet_rpc_client; uint64_t last_block_received; fc::future _listener_task; diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 40836cb6..7d030441 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -148,10 +148,14 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options( "Tuple of [Bitcoin public key, Bitcoin private key] (may specify multiple times)"); cli.add_options()("hive-sidechain-enabled", bpo::value()->default_value(false), "Hive sidechain handler enabled"); - cli.add_options()("hive-node-ip", bpo::value()->default_value("127.0.0.1"), "IP address of Hive node"); - cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "RPC port of Hive node"); - cli.add_options()("hive-node-rpc-user", bpo::value(), "Hive RPC user"); - cli.add_options()("hive-node-rpc-password", bpo::value(), "Hive RPC password"); + cli.add_options()("hive-node-ip", bpo::value()->default_value("127.0.0.1"), "Hive node IP address"); + cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "Hive node RPC port"); + cli.add_options()("hive-node-rpc-user", bpo::value(), "Hive node RPC user"); + cli.add_options()("hive-node-rpc-password", bpo::value(), "Hive node RPC password"); + cli.add_options()("hive-wallet-ip", bpo::value()->default_value("127.0.0.1"), "Hive wallet IP address"); + cli.add_options()("hive-wallet-rpc-port", bpo::value()->default_value(28091), "Hive wallet RPC port "); + cli.add_options()("hive-wallet-rpc-user", bpo::value(), "Hive wallet RPC user"); + cli.add_options()("hive-wallet-rpc-password", bpo::value(), "Hive wallet RPC password"); cli.add_options()("hive-private-key", bpo::value>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4", "5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n")), "Tuple of [Hive public key, Hive private key] (may specify multiple times)"); @@ -221,8 +225,10 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt sidechain_enabled_hive = options.at("hive-sidechain-enabled").as(); 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-node-rpc-user") && options.count("hive-node-rpc-password") &&*/ + options.count("hive-wallet-ip") && + options.count("hive-wallet-rpc-port") && + /*options.count("hive-wallet-rpc-user") && options.count("hive-wallet-rpc-password") &&*/ options.count("hive-private-key"); if (!config_ready_hive) { wlog("Haven't set up Hive sidechain parameters"); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 053ab857..9dfd7758 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -22,93 +23,80 @@ 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); +hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : + rpc_client(_ip, _port, _user, _password) { } -std::string hive_rpc_client::block_api_get_block(uint32_t block_number) { +std::string hive_node_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); + return send_post_request("block_api.get_block", params, false); } -std::string hive_rpc_client::database_api_get_dynamic_global_properties() { +std::string hive_node_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 ""; +hive_wallet_rpc_client::hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : + rpc_client(_ip, _port, _user, _password) { } -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 hive_wallet_rpc_client::get_account(std::string account) { + std::string params = "[\"" + account + "\"]"; + return send_post_request("get_account", params, true); +} - std::string url = "http://" + ip + ":" + std::to_string(rpc_port); +std::string hive_wallet_rpc_client::lock() { + return send_post_request("lock", "", true); +} - //if (wallet.length() > 0) { - // url = url + "/wallet/" + wallet; - //} +std::string hive_wallet_rpc_client::unlock(std::string password) { + std::string params = "[\"" + password + "\"]"; + return send_post_request("unlock", params, true); +} - fc::http::reply reply = conn.request("POST", url, body, fc::http::headers{authorization}); +std::string hive_wallet_rpc_client::update_account_auth_key(std::string account_name, std::string type, std::string public_key, std::string weight) { + std::string params = "[\"" + account_name + "\", \"" + type + "\", \"" + public_key + "\", " + weight + "]"; + return send_post_request("update_account_auth_key", params, true); +} - 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())); - } +std::string hive_wallet_rpc_client::update_account_auth_account(std::string account_name, std::string type, std::string auth_account, std::string weight) { + std::string params = "[\"" + account_name + "\", \"" + type + "\", \"" + auth_account + "\", " + weight + "]"; + return send_post_request("update_account_auth_account", params, true); +} - return reply; +std::string hive_wallet_rpc_client::update_account_auth_threshold(std::string account_name, std::string type, std::string threshold) { + std::string params = "[\"" + account_name + "\", \"" + type + "\", " + threshold + "]"; + return send_post_request("update_account_auth_account", params, true); } 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(); - rpc_port = options.at("hive-node-rpc-port").as(); + node_ip = options.at("hive-node-ip").as(); + node_rpc_port = options.at("hive-node-rpc-port").as(); if (options.count("hive-node-rpc-user")) { - rpc_user = options.at("hive-node-rpc-user").as(); + node_rpc_user = options.at("hive-node-rpc-user").as(); } else { - rpc_user = ""; + node_rpc_user = ""; } if (options.count("hive-node-rpc-password")) { - rpc_password = options.at("hive-node-rpc-password").as(); + node_rpc_password = options.at("hive-node-rpc-password").as(); } else { - rpc_password = ""; + node_rpc_password = ""; + } + + wallet_ip = options.at("hive-wallet-ip").as(); + wallet_rpc_port = options.at("hive-wallet-rpc-port").as(); + if (options.count("hive-wallet-rpc-user")) { + wallet_rpc_user = options.at("hive-wallet-rpc-user").as(); + } else { + wallet_rpc_user = ""; + } + if (options.count("hive-wallet-rpc-password")) { + wallet_rpc_password = options.at("hive-wallet-rpc-password").as(); + } else { + wallet_rpc_password = ""; } if (options.count("hive-private-key")) { @@ -125,13 +113,21 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi fc::http::connection conn; try { - conn.connect_to(fc::ip::endpoint(fc::ip::address(ip), rpc_port)); + conn.connect_to(fc::ip::endpoint(fc::ip::address(node_ip), node_rpc_port)); } catch (fc::exception &e) { - elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", ip)("port", rpc_port)); + elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); + FC_ASSERT(false); + } + try { + conn.connect_to(fc::ip::endpoint(fc::ip::address(wallet_ip), wallet_rpc_port)); + } catch (fc::exception &e) { + elog("No Hive wallet running at ${ip} or wrong rpc port: ${port}", ("ip", wallet_ip)("port", wallet_rpc_port)); FC_ASSERT(false); } - rpc_client = new hive_rpc_client(ip, rpc_port, rpc_user, rpc_password); + node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password); + + wallet_rpc_client = new hive_wallet_rpc_client(wallet_ip, wallet_rpc_port, wallet_rpc_user, wallet_rpc_password); last_block_received = 0; schedule_hive_listener(); @@ -215,11 +211,77 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { // elog("=================================================="); // } + should_approve = true; + return should_approve; } void sidechain_net_handler_hive::process_primary_wallet() { - return; + const auto &swi = database.get_index_type().indices().get(); + const auto &active_sw = swi.rbegin(); + if (active_sw != swi.rend()) { + + if ((active_sw->addresses.find(sidechain) == active_sw->addresses.end()) || + (active_sw->addresses.at(sidechain).empty())) { + + if (proposal_exists(chain::operation::tag::value, active_sw->id)) { + return; + } + + const chain::global_property_object &gpo = database.get_global_properties(); + + //auto active_sons = gpo.active_sons; + //string reply_str = create_primary_wallet_address(active_sons); + + //std::stringstream active_pw_ss(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()) { + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + 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); + + //std::stringstream res; + //boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); + + son_wallet_update_operation swu_op; + swu_op.payer = gpo.parameters.son_account(); + swu_op.son_wallet_id = active_sw->id; + swu_op.sidechain = sidechain; + swu_op.address = "son-account"; + + proposal_op.proposed_ops.emplace_back(swu_op); + + //const auto &prev_sw = std::next(active_sw); + //if (prev_sw != swi.rend()) { + // std::string new_pw_address = active_pw_pt.get("result.address"); + // std::string tx_str = create_primary_wallet_transaction(*prev_sw, new_pw_address); + // if (!tx_str.empty()) { + // sidechain_transaction_create_operation stc_op; + // stc_op.payer = gpo.parameters.son_account(); + // stc_op.object_id = prev_sw->id; + // stc_op.sidechain = sidechain; + // stc_op.transaction = tx_str; + // stc_op.signers = prev_sw->sons; + // proposal_op.proposed_ops.emplace_back(stc_op); + // } + //} + + 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)); + } catch (fc::exception &e) { + elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what())); + return; + } + //} + } + } } void sidechain_net_handler_hive::process_sidechain_addresses() { @@ -383,7 +445,7 @@ void sidechain_net_handler_hive::schedule_hive_listener() { void sidechain_net_handler_hive::hive_listener_loop() { schedule_hive_listener(); - std::string reply = rpc_client->database_api_get_dynamic_global_properties(); + std::string reply = node_rpc_client->database_api_get_dynamic_global_properties(); if (!reply.empty()) { std::stringstream ss(reply); @@ -401,7 +463,7 @@ void sidechain_net_handler_hive::hive_listener_loop() { } 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())); + std::string block = node_rpc_client->block_api_get_block(std::atoll(event_data.c_str())); if (block != "") { std::stringstream ss(block); boost::property_tree::ptree block_json; @@ -434,10 +496,10 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { } } - boost::property_tree::ptree transactions_json = block_json.get_child("result.block.transactions"); - ss.str(""); - boost::property_tree::write_json(ss, transactions_json); - elog("Transactions: ${ss}", ("ss", ss.str())); + //boost::property_tree::ptree transactions_json = block_json.get_child("result.block.transactions"); + //ss.str(""); + //boost::property_tree::write_json(ss, transactions_json); + //elog("Transactions: ${ss}", ("ss", ss.str())); //{"jsonrpc":"2.0","result":{"block":{"previous":"00006dd6c2b98bc7d1214f61f1c797bb22edb4cd","timestamp":"2021-03-10T12:18:21","witness":"initminer","transaction_merkle_root":"55d89a7b615a4d25f32d9160ce6714a5de5f2b05","extensions":[],"witness_signature":"1f0e2115cb18d862a279de93f3d4d82df4210984e26231db206de8b37e26b2aa8048f21fc7447f842047fea7ffa2a481eede07d379bf9577ab09b5395434508d86","transactions":[{"ref_block_num":28118,"ref_block_prefix":3347823042,"expiration":"2021-03-10T12:18:48","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f55c34b9fab328de76d7c4afd30ca1b64742f46d2aee759b66fc9b0e9d90653a44dbad1ef583c9578666abc23db0ca540f32746d7ac4ff7a6394d28a2c9ef29f3"]}],"block_id":"00006dd7a264f6a8d833ad88a7eeb3abdd483af3","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["73eb9d7a19b9bcb941500f4a9924c13fe3b94c4a"]}},"id":"block_api.get_block"} //{"jsonrpc":"2.0","result":{"block":{"previous":"00006de5714685397129f52693504ed3abde8e44","timestamp":"2021-03-10T12:19:06","witness":"initminer","transaction_merkle_root":"8b9bcb4b0aed33624a68abdf2860e76136ae9313","extensions":[],"witness_signature":"20f0743c1c3f63230f8af615e14ca0c5143ddfde0c5cee83c24486276223ceb21e7950f1b503750aad73f979bbdf6a298c9e22a079cc1397ed9d4a6eb8aeccea79","transactions":[{"ref_block_num":28133,"ref_block_prefix":965035633,"expiration":"2021-03-10T12:19:33","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f519b0e13ee672108670540f846ad7cef676c94e3169e2d4c3ff12b5dad6dc412154cb45677b2caa0f839b5e2826ae96d6bbf36987ab40a928c3e0081e10a082e"]}],"block_id":"00006de655bac50cb40e05fc02eaef112ccae454","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["28c09bb777827fbf41023c50600aef65e0c83a8b"]}},"id":"block_api.get_block"} @@ -445,7 +507,7 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { //const auto &vins = extract_info_from_block(block); - const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); + //const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); /*for (const auto &v : vins) { // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT -- 2.45.2 From 7fc964103ed0450cdf109cad984e6f08cdfe9926 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 22 Mar 2021 17:29:35 +0100 Subject: [PATCH 04/57] Hive transaction handling, WIP --- .../peerplays_sidechain/CMakeLists.txt | 2 + .../peerplays_sidechain/common/rpc_client.cpp | 14 +++ .../peerplays_sidechain/hive/transaction.cpp | 42 +++++++ .../peerplays_sidechain/hive/types.cpp | 77 +++++++++++++ .../peerplays_sidechain/common/rpc_client.hpp | 5 +- .../peerplays_sidechain/hive/authority.hpp | 34 ++++++ .../hive/hive_operations.hpp | 26 +++++ .../peerplays_sidechain/hive/operations.hpp | 13 +++ .../peerplays_sidechain/hive/transaction.hpp | 43 +++++++ .../peerplays_sidechain/hive/types.hpp | 61 ++++++++++ .../sidechain_net_handler_hive.hpp | 8 ++ .../sidechain_net_handler_hive.cpp | 105 ++++++++++++------ 12 files changed, 395 insertions(+), 35 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/hive/transaction.cpp create mode 100644 libraries/plugins/peerplays_sidechain/hive/types.cpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 6b5b147e..21c73bb0 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -15,6 +15,8 @@ add_library( peerplays_sidechain bitcoin/utils.cpp bitcoin/sign_bitcoin_transaction.cpp common/rpc_client.cpp + hive/transaction.cpp + hive/types.cpp ) if (ENABLE_DEV_FEATURES) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 6570f181..a2806ae5 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -21,6 +21,20 @@ rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std:: authorization.val = "Basic " + fc::base64_encode(user + ":" + password); } +std::string rpc_client::retrieve_value_from_reply(std::string reply_str, std::string value_path) { + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + if (json.find("result") == json.not_found()) { + return ""; + } + auto json_result = json.get_child("result"); + if (json_result.find(value_path) == json_result.not_found()) { + return ""; + } + return json_result.get(value_path); +} + std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log) { std::stringstream body; diff --git a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp new file mode 100644 index 00000000..4833e62f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp @@ -0,0 +1,42 @@ +#include + +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +digest_type transaction::sig_digest(const chain_id_type &chain_id) const { + digest_type::encoder enc; + fc::raw::pack(enc, chain_id); + fc::raw::pack(enc, *this); + return enc.result(); +} + +void transaction::set_expiration(fc::time_point_sec expiration_time) { + expiration = expiration_time; +} + +void transaction::set_reference_block(const block_id_type &reference_block) { + ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]); + ref_block_prefix = reference_block._hash[1]; +} + +void signed_transaction::clear() { + operations.clear(); + signatures.clear(); +} + +const signature_type &signed_transaction::sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) { + digest_type h = sig_digest(chain_id); + signatures.push_back(key.sign_compact(h, true)); + return signatures.back(); +} + +signature_type signed_transaction::sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) const { + digest_type::encoder enc; + fc::raw::pack(enc, chain_id); + fc::raw::pack(enc, *this); + return key.sign_compact(enc.result(), true); +} + +}}} // namespace graphene::peerplays_sidechain::hive diff --git a/libraries/plugins/peerplays_sidechain/hive/types.cpp b/libraries/plugins/peerplays_sidechain/hive/types.cpp new file mode 100644 index 00000000..7486ce28 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/types.cpp @@ -0,0 +1,77 @@ +#include + +#include +#include +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +#define ADDRESS_PREFIX "TST" + +public_key_type::public_key_type() : + key_data(){}; + +public_key_type::public_key_type(const fc::ecc::public_key_data &data) : + key_data(data){}; + +public_key_type::public_key_type(const fc::ecc::public_key &pubkey) : + key_data(pubkey){}; + +public_key_type::public_key_type(const std::string &base58str) { + // TODO: Refactor syntactic checks into static is_valid() + // to make public_key_type API more similar to address API + std::string prefix(ADDRESS_PREFIX); + + const size_t prefix_len = prefix.size(); + FC_ASSERT(base58str.size() > prefix_len); + FC_ASSERT(base58str.substr(0, prefix_len) == prefix, "", ("base58str", base58str)); + auto bin = fc::from_base58(base58str.substr(prefix_len)); + auto bin_key = fc::raw::unpack(bin); + key_data = bin_key.data; + FC_ASSERT(fc::ripemd160::hash(key_data.data, key_data.size())._hash[0] == bin_key.check); +}; + +public_key_type::operator fc::ecc::public_key_data() const { + return key_data; +}; + +public_key_type::operator fc::ecc::public_key() const { + return fc::ecc::public_key(key_data); +}; + +public_key_type::operator std::string() const { + binary_key k; + k.data = key_data; + k.check = fc::ripemd160::hash(k.data.data, k.data.size())._hash[0]; + auto data = fc::raw::pack(k); + return ADDRESS_PREFIX + fc::to_base58(data.data(), data.size()); +} + +bool operator==(const public_key_type &p1, const fc::ecc::public_key &p2) { + return p1.key_data == p2.serialize(); +} + +bool operator==(const public_key_type &p1, const public_key_type &p2) { + return p1.key_data == p2.key_data; +} + +bool operator!=(const public_key_type &p1, const public_key_type &p2) { + return p1.key_data != p2.key_data; +} + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +using namespace std; + +void to_variant(const graphene::peerplays_sidechain::hive::public_key_type &var, fc::variant &vo, uint32_t max_depth) { + vo = std::string(var); +} + +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::public_key_type &vo, uint32_t max_depth) { + vo = graphene::peerplays_sidechain::hive::public_key_type(var.as_string()); +} + +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index 04b88361..6ee56f72 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -12,8 +12,8 @@ public: rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); protected: + 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); - fc::http::reply send_post_request(std::string body, bool show_log); std::string ip; uint32_t port; @@ -23,6 +23,9 @@ protected: uint32_t request_id; fc::http::header authorization; + +private: + fc::http::reply send_post_request(std::string body, bool show_log); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp new file mode 100644 index 00000000..f3bb828f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct authority { + authority() { + } + + enum classification { + owner = 0, + active = 1, + key = 2, + posting = 3 + }; + + uint32_t weight_threshold = 0; + fc::flat_map account_auths; + fc::flat_map key_auths; +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT_ENUM(graphene::peerplays_sidechain::hive::authority::classification, + (owner)(active)(key)(posting)) + +FC_REFLECT(graphene::peerplays_sidechain::hive::authority, + (weight_threshold)(account_auths)(key_auths)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp new file mode 100644 index 00000000..9d03b07f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include + +#include +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct account_update_operation { + std::string account; + fc::optional owner; + fc::optional active; + fc::optional posting; + hive::public_key_type memo_key; + std::string json_metadata; +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT(graphene::peerplays_sidechain::hive::account_update_operation, + (account)(owner)(active)(posting)(memo_key)(json_metadata)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp new file mode 100644 index 00000000..942469e2 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +typedef fc::static_variant< + account_update_operation> + hive_operation; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT_TYPENAME(graphene::peerplays_sidechain::hive::hive_operation) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp new file mode 100644 index 00000000..92c47b44 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#include +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct transaction { + uint16_t ref_block_num = 0; + uint32_t ref_block_prefix = 0; + fc::time_point_sec expiration; + std::vector operations; + extensions_type extensions; + std::vector signatures; + + digest_type sig_digest(const chain_id_type &chain_id) const; + + void set_expiration(fc::time_point_sec expiration_time); + void set_reference_block(const block_id_type &reference_block); +}; + +struct signed_transaction : public transaction { + + std::vector signatures; + + const signature_type &sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id); + signature_type sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) const; + void clear(); +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT(graphene::peerplays_sidechain::hive::transaction, + (ref_block_num)(ref_block_prefix)(expiration)(operations)(extensions)) + +FC_REFLECT_DERIVED(graphene::peerplays_sidechain::hive::signed_transaction, + (graphene::peerplays_sidechain::hive::transaction), + (signatures)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp new file mode 100644 index 00000000..0b7c4f35 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct void_t {}; + +typedef fc::static_variant future_extensions; +typedef fc::flat_set extensions_type; + +typedef fc::ecc::private_key private_key_type; +typedef fc::sha256 chain_id_type; +//typedef fixed_string<16> account_name_type; +typedef fc::ripemd160 block_id_type; +//typedef fc::ripemd160 checksum_type; +//typedef fc::ripemd160 transaction_id_type; +typedef fc::sha256 digest_type; +typedef fc::ecc::compact_signature signature_type; +//typedef safe share_type; +//typedef safe ushare_type; +//typedef uint16_t weight_type; +//typedef uint32_t contribution_id_type; +//typedef fixed_string<32> custom_id_type; + +struct public_key_type { + struct binary_key { + binary_key() { + } + uint32_t check = 0; + fc::ecc::public_key_data data; + }; + fc::ecc::public_key_data key_data; + public_key_type(); + public_key_type(const fc::ecc::public_key_data &data); + public_key_type(const fc::ecc::public_key &pubkey); + explicit public_key_type(const std::string &base58str); + operator fc::ecc::public_key_data() const; + operator fc::ecc::public_key() const; + explicit operator std::string() const; + friend bool operator==(const public_key_type &p1, const fc::ecc::public_key &p2); + friend bool operator==(const public_key_type &p1, const public_key_type &p2); + friend bool operator<(const public_key_type &p1, const public_key_type &p2) { + return p1.key_data < p2.key_data; + } + friend bool operator!=(const public_key_type &p1, const public_key_type &p2); +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { +void to_variant(const graphene::peerplays_sidechain::hive::public_key_type &var, fc::variant &vo, uint32_t max_depth = 2); +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::public_key_type &vo, uint32_t max_depth = 2); +} // namespace fc + +FC_REFLECT(graphene::peerplays_sidechain::hive::public_key_type, (key_data)) +FC_REFLECT(graphene::peerplays_sidechain::hive::public_key_type::binary_key, (data)(check)) + +FC_REFLECT(graphene::peerplays_sidechain::hive::void_t, ) +FC_REFLECT_TYPENAME(graphene::peerplays_sidechain::hive::future_extensions) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 59ce174d..62ad9253 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -17,6 +17,11 @@ public: std::string block_api_get_block(uint32_t block_number); std::string database_api_get_dynamic_global_properties(); + std::string database_api_get_version(); + + std::string get_chain_id(); + std::string get_head_block_id(); + std::string get_head_block_time(); }; class hive_wallet_rpc_client : public rpc_client { @@ -24,11 +29,14 @@ public: hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); std::string get_account(std::string account); + std::string info(); std::string lock(); std::string unlock(std::string password); std::string update_account_auth_key(std::string account_name, std::string type, std::string public_key, std::string weight); std::string update_account_auth_account(std::string account_name, std::string type, std::string auth_account, std::string weight); std::string update_account_auth_threshold(std::string account_name, std::string type, std::string threshold); + + std::string get_account_memo_key(std::string account); }; class sidechain_net_handler_hive : public sidechain_net_handler { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 9dfd7758..455bd569 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -13,12 +13,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include namespace graphene { namespace peerplays_sidechain { @@ -36,6 +39,25 @@ std::string hive_node_rpc_client::database_api_get_dynamic_global_properties() { return send_post_request("database_api.get_dynamic_global_properties", "", false); } +std::string hive_node_rpc_client::database_api_get_version() { + return send_post_request("database_api.get_version", "", true); +} + +std::string hive_node_rpc_client::get_chain_id() { + std::string reply_str = database_api_get_version(); + return retrieve_value_from_reply(reply_str, "chain_id"); +} + +std::string hive_node_rpc_client::get_head_block_id() { + std::string reply_str = database_api_get_dynamic_global_properties(); + return retrieve_value_from_reply(reply_str, "head_block_id"); +} + +std::string hive_node_rpc_client::get_head_block_time() { + std::string reply_str = database_api_get_dynamic_global_properties(); + return retrieve_value_from_reply(reply_str, "time"); +} + hive_wallet_rpc_client::hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : rpc_client(_ip, _port, _user, _password) { } @@ -49,6 +71,10 @@ std::string hive_wallet_rpc_client::lock() { return send_post_request("lock", "", true); } +std::string hive_wallet_rpc_client::info() { + return send_post_request("info", "", true); +} + std::string hive_wallet_rpc_client::unlock(std::string password) { std::string params = "[\"" + password + "\"]"; return send_post_request("unlock", params, true); @@ -69,6 +95,11 @@ std::string hive_wallet_rpc_client::update_account_auth_threshold(std::string ac return send_post_request("update_account_auth_account", params, true); } +std::string hive_wallet_rpc_client::get_account_memo_key(std::string account) { + std::string reply_str = get_account(account); + return retrieve_value_from_reply(reply_str, "memo_key"); +} + 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; @@ -230,22 +261,53 @@ void sidechain_net_handler_hive::process_primary_wallet() { const chain::global_property_object &gpo = database.get_global_properties(); - //auto active_sons = gpo.active_sons; - //string reply_str = create_primary_wallet_address(active_sons); + auto active_sons = gpo.active_sons; + fc::flat_map account_auths; + uint32_t total_weight = 0; + for (const auto &active_son : active_sons) { + total_weight = total_weight + active_son.weight; + account_auths[active_son.sidechain_public_keys.at(sidechain)] = active_son.weight; + } - //std::stringstream active_pw_ss(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()) { + std::string memo_key = wallet_rpc_client->get_account_memo_key("son-account"); + if (memo_key.empty()) { + return; + } + + hive::authority active; + active.weight_threshold = 1; + active.account_auths = account_auths; + + hive::account_update_operation auo; + auo.account = "son-account"; + auo.active = active; + auo.memo_key = hive::public_key_type(memo_key); + + std::string block_id_str = node_rpc_client->get_head_block_id(); + hive::block_id_type head_block_id(block_id_str); + + std::string head_block_time_str = node_rpc_client->get_head_block_time(); + time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str); + + hive::signed_transaction htrx; + htrx.set_reference_block(head_block_id); + htrx.set_expiration(head_block_time + fc::seconds(90)); + + htrx.operations.push_back(auo); + ilog("TRX: ${htrx}", ("htrx", htrx)); + + std::string chain_id_str = node_rpc_client->get_chain_id(); + const hive::chain_id_type chain_id(chain_id_str); + + // create sidechain transaction for wallet update, to collect SON signatures + + return; // temporary proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; 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); - //std::stringstream res; - //boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); - son_wallet_update_operation swu_op; swu_op.payer = gpo.parameters.son_account(); swu_op.son_wallet_id = active_sw->id; @@ -254,21 +316,6 @@ void sidechain_net_handler_hive::process_primary_wallet() { proposal_op.proposed_ops.emplace_back(swu_op); - //const auto &prev_sw = std::next(active_sw); - //if (prev_sw != swi.rend()) { - // std::string new_pw_address = active_pw_pt.get("result.address"); - // std::string tx_str = create_primary_wallet_transaction(*prev_sw, new_pw_address); - // if (!tx_str.empty()) { - // sidechain_transaction_create_operation stc_op; - // stc_op.payer = gpo.parameters.son_account(); - // stc_op.object_id = prev_sw->id; - // stc_op.sidechain = sidechain; - // stc_op.transaction = tx_str; - // stc_op.signers = prev_sw->sons; - // proposal_op.proposed_ops.emplace_back(stc_op); - // } - //} - signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); try { trx.validate(); @@ -279,7 +326,6 @@ void sidechain_net_handler_hive::process_primary_wallet() { elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what())); return; } - //} } } } @@ -496,15 +542,6 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { } } - //boost::property_tree::ptree transactions_json = block_json.get_child("result.block.transactions"); - //ss.str(""); - //boost::property_tree::write_json(ss, transactions_json); - //elog("Transactions: ${ss}", ("ss", ss.str())); - - //{"jsonrpc":"2.0","result":{"block":{"previous":"00006dd6c2b98bc7d1214f61f1c797bb22edb4cd","timestamp":"2021-03-10T12:18:21","witness":"initminer","transaction_merkle_root":"55d89a7b615a4d25f32d9160ce6714a5de5f2b05","extensions":[],"witness_signature":"1f0e2115cb18d862a279de93f3d4d82df4210984e26231db206de8b37e26b2aa8048f21fc7447f842047fea7ffa2a481eede07d379bf9577ab09b5395434508d86","transactions":[{"ref_block_num":28118,"ref_block_prefix":3347823042,"expiration":"2021-03-10T12:18:48","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f55c34b9fab328de76d7c4afd30ca1b64742f46d2aee759b66fc9b0e9d90653a44dbad1ef583c9578666abc23db0ca540f32746d7ac4ff7a6394d28a2c9ef29f3"]}],"block_id":"00006dd7a264f6a8d833ad88a7eeb3abdd483af3","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["73eb9d7a19b9bcb941500f4a9924c13fe3b94c4a"]}},"id":"block_api.get_block"} - //{"jsonrpc":"2.0","result":{"block":{"previous":"00006de5714685397129f52693504ed3abde8e44","timestamp":"2021-03-10T12:19:06","witness":"initminer","transaction_merkle_root":"8b9bcb4b0aed33624a68abdf2860e76136ae9313","extensions":[],"witness_signature":"20f0743c1c3f63230f8af615e14ca0c5143ddfde0c5cee83c24486276223ceb21e7950f1b503750aad73f979bbdf6a298c9e22a079cc1397ed9d4a6eb8aeccea79","transactions":[{"ref_block_num":28133,"ref_block_prefix":965035633,"expiration":"2021-03-10T12:19:33","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f519b0e13ee672108670540f846ad7cef676c94e3169e2d4c3ff12b5dad6dc412154cb45677b2caa0f839b5e2826ae96d6bbf36987ab40a928c3e0081e10a082e"]}],"block_id":"00006de655bac50cb40e05fc02eaef112ccae454","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["28c09bb777827fbf41023c50600aef65e0c83a8b"]}},"id":"block_api.get_block"} - //{"jsonrpc":"2.0","result":{"block":{"previous":"00006dfe471f2224d4b6c3189c7a2a5ed261c277","timestamp":"2021-03-10T12:20:21","witness":"initminer","transaction_merkle_root":"e407272ab2e383e5fef487651d88e0c0c3617e29","extensions":[],"witness_signature":"1f48152244ad2036e3761248a93a9c38fb8c7ee8a0721f9f47ae267b63808e56c223ab15641ec2baad6be4a54db5df04ead9b7f1107dba267a89c02c49d8115fbf","transactions":[{"ref_block_num":28158,"ref_block_prefix":606216007,"expiration":"2021-03-10T12:20:48","operations":[{"type":"transfer_operation","value":{"from":"initminer","to":"deepcrypto8","amount":{"amount":"100000000","precision":3,"nai":"@@000000021"},"memo":""}}],"extensions":[],"signatures":["1f5b4c7a8695b6c68b6ee96000367ffa96c23d9f4ed8ca36f639b38351b8198d18626f3b8277ca5c92bd537c68db5f9730f3f9df59a8ce631e9dcf7ce53032796b"]}],"block_id":"00006dff4bcd9a790193924fe44d0bdc3fde1c83","signing_key":"TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4","transaction_ids":["50b8f4b268a0fa3a34698dd6f8152117343e6c06"]}},"id":"block_api.get_block"} - //const auto &vins = extract_info_from_block(block); //const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); -- 2.45.2 From 44f81d4d088259f3fcf49054056b5b81ccb671f3 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 24 Mar 2021 11:59:38 +0100 Subject: [PATCH 05/57] Collecting Hive SONs signatures --- .../peerplays_sidechain/hive/transaction.cpp | 20 ++++- .../peerplays_sidechain/hive/types.cpp | 2 - .../peerplays_sidechain/hive/authority.hpp | 2 +- .../peerplays_sidechain/hive/transaction.hpp | 1 - .../peerplays_sidechain/hive/types.hpp | 2 +- .../sidechain_net_handler_hive.hpp | 3 + .../sidechain_net_handler_hive.cpp | 87 ++++++++++++------- 7 files changed, 81 insertions(+), 36 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp index 4833e62f..6b2da082 100644 --- a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include @@ -28,7 +30,23 @@ void signed_transaction::clear() { const signature_type &signed_transaction::sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) { digest_type h = sig_digest(chain_id); - signatures.push_back(key.sign_compact(h, true)); + auto sig = key.sign_compact(h, true); + + ilog("Signing1: chain_id = ${chain_id}", ("chain_id", chain_id)); + ilog("Signing1: key = ${key}", ("key", key)); + ilog("Signing1: this = ${this}", ("this", *this)); + ilog("Signing1: h = ${h}", ("h", h)); + ilog("Signing1: signature = ${sig}", ("sig", sig)); + + std::stringstream ss_st; + fc::raw::pack(ss_st, chain_id); + ilog("Signing: ${ss_st}", ("ss_st", boost::algorithm::hex(ss_st.str()))); + + ss_st.str(""); + fc::raw::pack(ss_st, *this); + ilog("Signing: ${ss_st}", ("ss_st", boost::algorithm::hex(ss_st.str()))); + + signatures.push_back(sig); return signatures.back(); } diff --git a/libraries/plugins/peerplays_sidechain/hive/types.cpp b/libraries/plugins/peerplays_sidechain/hive/types.cpp index 7486ce28..c2436701 100644 --- a/libraries/plugins/peerplays_sidechain/hive/types.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/types.cpp @@ -19,8 +19,6 @@ public_key_type::public_key_type(const fc::ecc::public_key &pubkey) : key_data(pubkey){}; public_key_type::public_key_type(const std::string &base58str) { - // TODO: Refactor syntactic checks into static is_valid() - // to make public_key_type API more similar to address API std::string prefix(ADDRESS_PREFIX); const size_t prefix_len = prefix.size(); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp index f3bb828f..1a937f0f 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp @@ -21,7 +21,7 @@ struct authority { }; uint32_t weight_threshold = 0; - fc::flat_map account_auths; + fc::flat_map account_auths; fc::flat_map key_auths; }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp index 92c47b44..6d1de526 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp @@ -16,7 +16,6 @@ struct transaction { fc::time_point_sec expiration; std::vector operations; extensions_type extensions; - std::vector signatures; digest_type sig_digest(const chain_id_type &chain_id) const; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp index 0b7c4f35..13bf80fe 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -12,7 +12,7 @@ typedef fc::flat_set extensions_type; typedef fc::ecc::private_key private_key_type; typedef fc::sha256 chain_id_type; -//typedef fixed_string<16> account_name_type; +typedef std::string account_name_type; typedef fc::ripemd160 block_id_type; //typedef fc::ripemd160 checksum_type; //typedef fc::ripemd160 transaction_id_type; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 62ad9253..d5f7b646 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace graphene { namespace peerplays_sidechain { @@ -66,6 +67,8 @@ private: std::string wallet_rpc_password; hive_wallet_rpc_client *wallet_rpc_client; + hive::chain_id_type chain_id; + uint64_t last_block_received; fc::future _listener_task; fc::signal event_received; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 455bd569..ec18751d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -40,7 +40,7 @@ std::string hive_node_rpc_client::database_api_get_dynamic_global_properties() { } std::string hive_node_rpc_client::database_api_get_version() { - return send_post_request("database_api.get_version", "", true); + return send_post_request("database_api.get_version", "", false); } std::string hive_node_rpc_client::get_chain_id() { @@ -160,6 +160,9 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi wallet_rpc_client = new hive_wallet_rpc_client(wallet_ip, wallet_rpc_port, wallet_rpc_user, wallet_rpc_password); + std::string chain_id_str = node_rpc_client->get_chain_id(); + chain_id = chain_id_type(chain_id_str); + last_block_received = 0; schedule_hive_listener(); event_received.connect([this](const std::string &event_data) { @@ -296,12 +299,12 @@ void sidechain_net_handler_hive::process_primary_wallet() { htrx.operations.push_back(auo); ilog("TRX: ${htrx}", ("htrx", htrx)); - std::string chain_id_str = node_rpc_client->get_chain_id(); - const hive::chain_id_type chain_id(chain_id_str); - - // create sidechain transaction for wallet update, to collect SON signatures - - return; // temporary + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + std::string tx_str = boost::algorithm::hex(ss.str()); + if (tx_str.empty()) { + return; + } proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; @@ -316,6 +319,15 @@ void sidechain_net_handler_hive::process_primary_wallet() { proposal_op.proposed_ops.emplace_back(swu_op); + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = active_sw->id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + + proposal_op.proposed_ops.emplace_back(stc_op); + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); try { trx.validate(); @@ -426,37 +438,52 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob 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 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_trx(boost::algorithm::unhex(sto.transaction)); + hive::signed_transaction htrx; + fc::raw::unpack(ss_trx, htrx, 1000); + + // temp + // sign_transaction {"ref_block_num":0,"ref_block_prefix":0,"expiration":"1970-01-01T00:00:0","operations":[["account_update",{"account":"son-account","active":{"weight_threshold":1,"account_auths":[["sonaccount01",1],["sonaccount02",1],["sonaccount03",1],["sonaccount04",1],["sonaccount05",1],["sonaccount06",1],["sonaccount07",1],["sonaccount08",1],["sonaccount09",1],["sonaccount10",1],["sonaccount11",1],["sonaccount12",1],["sonaccount13",1],["sonaccount14",1],["sonaccount15",1]],"key_auths":[]},"memo_key":"TST78bZV5JsuNKUVM7WDVKBnuiuXBTR8gsPEaev2fj96iXqq5R13u","json_metadata":""}]],"extensions":[]} false + htrx.set_reference_block(block_id_type("0000d68fd4d7abb7e8975398b9e93f93db990ac8")); + htrx.set_expiration(fc::time_point::from_iso_string("2021-03-23T19:21:24")); + // temp + + ilog("TRX: ${htrx}", ("htrx", htrx)); + ilog("EXP: {\"ref_block_num\":54927,\"ref_block_prefix\":3081492436,\"expiration\":\"2021-03-23T19:21:24\",\"operations\":[{\"type\":\"account_update_operation\",\"value\":{\"account\":\"son-account\",\"active\":{\"weight_threshold\":1,\"account_auths\":[[\"sonaccount01\",1],[\"sonaccount02\",1],[\"sonaccount03\",1],[\"sonaccount04\",1],[\"sonaccount05\",1],[\"sonaccount06\",1],[\"sonaccount07\",1],[\"sonaccount08\",1],[\"sonaccount09\",1],[\"sonaccount10\",1],[\"sonaccount11\",1],[\"sonaccount12\",1],[\"sonaccount13\",1],[\"sonaccount14\",1],[\"sonaccount15\",1]],\"key_auths\":[]},\"memo_key\":\"TST1111111111111111111111111111111114T1Anm\",\"json_metadata\":\"\"}}],\"extensions\":[],\"signatures\":[\"1f323561e46aa7703850d6afc5fdf00b338424eed695c9513568135bb5dbc051f3242a463f29d17257d982ae616214239b5405073ae7771469a7ea9e36c1577c45\"]}"); + + std::string chain_id_str = node_rpc_client->get_chain_id(); + const hive::chain_id_type chain_id(chain_id_str); + + fc::optional privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))); + signature_type st = htrx.sign(*privkey, chain_id); + + ilog("TRX: ${htrx}", ("htrx", htrx)); + ilog("EXP: {\"ref_block_num\":54927,\"ref_block_prefix\":3081492436,\"expiration\":\"2021-03-23T19:21:24\",\"operations\":[{\"type\":\"account_update_operation\",\"value\":{\"account\":\"son-account\",\"active\":{\"weight_threshold\":1,\"account_auths\":[[\"sonaccount01\",1],[\"sonaccount02\",1],[\"sonaccount03\",1],[\"sonaccount04\",1],[\"sonaccount05\",1],[\"sonaccount06\",1],[\"sonaccount07\",1],[\"sonaccount08\",1],[\"sonaccount09\",1],[\"sonaccount10\",1],[\"sonaccount11\",1],[\"sonaccount12\",1],[\"sonaccount13\",1],[\"sonaccount14\",1],[\"sonaccount15\",1]],\"key_auths\":[]},\"memo_key\":\"TST1111111111111111111111111111111114T1Anm\",\"json_metadata\":\"\"}}],\"extensions\":[],\"signatures\":[\"1f323561e46aa7703850d6afc5fdf00b338424eed695c9513568135bb5dbc051f3242a463f29d17257d982ae616214239b5405073ae7771469a7ea9e36c1577c45\"]}"); + std::stringstream ss_st; - // fc::raw::pack(ss_st, st, 1000); + fc::raw::pack(ss_st, st, 1000); std::string st_str = boost::algorithm::hex(ss_st.str()); + 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(); - // } - // } - // + std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); + hive::signed_transaction htrx; + fc::raw::unpack(ss_trx, htrx, 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); + htrx.signatures.push_back(st); + } + } + ilog("HTRX: ${htrx}", ("htrx", htrx)); + // try { // trx.validate(); // database.push_transaction(trx, database::validation_steps::skip_block_size_check); -- 2.45.2 From a2c5c29005f29c31f7d9b10d79528fdcb8bca555 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 30 Mar 2021 11:11:07 +0200 Subject: [PATCH 06/57] Proper account_update_operation serialization and transaction signing --- .../peerplays_sidechain/CMakeLists.txt | 1 + .../peerplays_sidechain/hive/operations.cpp | 101 ++++++++++++++++++ .../peerplays_sidechain/hive/authority.hpp | 5 +- .../hive/hive_operations.hpp | 32 +++++- .../peerplays_sidechain/hive/operations.hpp | 21 ++++ .../sidechain_net_handler_hive.hpp | 1 + .../sidechain_net_handler_hive.cpp | 21 ++-- 7 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/hive/operations.cpp diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 21c73bb0..ca0f56ef 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -15,6 +15,7 @@ add_library( peerplays_sidechain bitcoin/utils.cpp bitcoin/sign_bitcoin_transaction.cpp common/rpc_client.cpp + hive/operations.cpp hive/transaction.cpp hive/types.cpp ) diff --git a/libraries/plugins/peerplays_sidechain/hive/operations.cpp b/libraries/plugins/peerplays_sidechain/hive/operations.cpp new file mode 100644 index 00000000..3a6ca812 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/operations.cpp @@ -0,0 +1,101 @@ +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +static std::string trim_typename_namespace(const std::string &name) { + auto start = name.find_last_of(':'); + start = (start == std::string::npos) ? 0 : start + 1; + return name.substr(start); +} + +struct from_static_variant_for_hive { + variant &var; + from_static_variant_for_hive(variant &dv) : + var(dv) { + } + + typedef void result_type; + template + void operator()(const T &v) const { + auto name = trim_typename_namespace(fc::get_typename::name()); + variant value; + to_variant(v, value, 5); + var = mutable_variant_object("type", name).set("value", value); + } +}; + +struct to_static_variant_for_hive { + const variant &var; + to_static_variant_for_hive(const variant &dv) : + var(dv) { + } + + typedef void result_type; + template + void operator()(T &v) const { + from_variant(var, v, 5); + } +}; + +struct get_static_variant_name { + string &name; + get_static_variant_name(string &n) : + name(n) { + } + + typedef void result_type; + template + void operator()(T &v) const { + name = trim_typename_namespace(fc::get_typename::name()); + } +}; + +void to_variant(const graphene::peerplays_sidechain::hive::hive_operation &var, fc::variant &vo, uint32_t max_depth) { + var.visit(from_static_variant_for_hive(vo)); +} + +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::hive_operation &vo, uint32_t max_depth) { + static std::map to_tag = []() { + std::map name_map; + for (int i = 0; i < graphene::peerplays_sidechain::hive::hive_operation::count(); ++i) { + graphene::peerplays_sidechain::hive::hive_operation tmp; + tmp.set_which(i); + string n; + tmp.visit(get_static_variant_name(n)); + name_map[n] = i; + } + return name_map; + }(); + + auto ar = var.get_array(); + if (ar.size() < 2) + return; + auto var_second = ar[1]; + + FC_ASSERT(var_second.is_object(), "Input data have to treated as object."); + auto v_object = var_second.get_object(); + + FC_ASSERT(v_object.contains("type"), "Type field doesn't exist."); + FC_ASSERT(v_object.contains("value"), "Value field doesn't exist."); + + int64_t which = -1; + + if (v_object["type"].is_integer()) { + which = v_object["type"].as_int64(); + } else { + auto itr = to_tag.find(v_object["type"].as_string()); + FC_ASSERT(itr != to_tag.end(), "Invalid object name: ${n}", ("n", v_object["type"])); + which = itr->second; + } + + vo.set_which(which); + vo.visit(fc::to_static_variant_for_hive(v_object["value"])); +} + +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp index 1a937f0f..bd67ae23 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include @@ -21,8 +20,8 @@ struct authority { }; uint32_t weight_threshold = 0; - fc::flat_map account_auths; - fc::flat_map key_auths; + fc::flat_map account_auths; + fc::flat_map key_auths; }; }}} // namespace graphene::peerplays_sidechain::hive diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp index 9d03b07f..cac3b03f 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp @@ -11,8 +11,28 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { +struct vote_operation {}; + +struct comment_operation {}; + +struct transfer_operation {}; + +struct transfer_to_vesting_operation {}; + +struct withdraw_vesting_operation {}; + +struct limit_order_create_operation {}; + +struct limit_order_cancel_operation {}; + +struct feed_publish_operation {}; + +struct convert_operation {}; + +struct account_create_operation {}; + struct account_update_operation { - std::string account; + hive::account_name_type account; fc::optional owner; fc::optional active; fc::optional posting; @@ -22,5 +42,15 @@ struct account_update_operation { }}} // namespace graphene::peerplays_sidechain::hive +FC_REFLECT(graphene::peerplays_sidechain::hive::vote_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::comment_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_vesting_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::withdraw_vesting_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_cancel_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::feed_publish_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::convert_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_create_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::account_update_operation, (account)(owner)(active)(posting)(memo_key)(json_metadata)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp index 942469e2..42550dc2 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp @@ -5,9 +5,30 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { typedef fc::static_variant< + vote_operation, + comment_operation, + + transfer_operation, + transfer_to_vesting_operation, + withdraw_vesting_operation, + + limit_order_create_operation, + limit_order_cancel_operation, + + feed_publish_operation, + convert_operation, + + account_create_operation, account_update_operation> hive_operation; }}} // namespace graphene::peerplays_sidechain::hive +namespace fc { + +void to_variant(const graphene::peerplays_sidechain::hive::hive_operation &var, fc::variant &vo, uint32_t max_depth = 5); +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::hive_operation &vo, uint32_t max_depth = 5); + +} // namespace fc + FC_REFLECT_TYPENAME(graphene::peerplays_sidechain::hive::hive_operation) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index d5f7b646..cb9a1f81 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -19,6 +19,7 @@ public: std::string block_api_get_block(uint32_t block_number); std::string database_api_get_dynamic_global_properties(); std::string database_api_get_version(); + std::string network_broadcast_api_broadcast_transaction(std::string htrx); std::string get_chain_id(); std::string get_head_block_id(); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index ec18751d..d5bd1a39 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,11 @@ std::string hive_node_rpc_client::database_api_get_version() { return send_post_request("database_api.get_version", "", false); } +std::string hive_node_rpc_client::network_broadcast_api_broadcast_transaction(std::string htrx) { + std::string params = "{ \"trx\": " + htrx + ", \"max_block_age\": -1 }"; + return send_post_request("network_broadcast_api.broadcast_transaction", params, true); +} + std::string hive_node_rpc_client::get_chain_id() { std::string reply_str = database_api_get_version(); return retrieve_value_from_reply(reply_str, "chain_id"); @@ -278,7 +284,7 @@ void sidechain_net_handler_hive::process_primary_wallet() { } hive::authority active; - active.weight_threshold = 1; + active.weight_threshold = total_weight * 2 / 3 + 1; active.account_auths = account_auths; hive::account_update_operation auo; @@ -442,14 +448,7 @@ std::string sidechain_net_handler_hive::process_sidechain_transaction(const side hive::signed_transaction htrx; fc::raw::unpack(ss_trx, htrx, 1000); - // temp - // sign_transaction {"ref_block_num":0,"ref_block_prefix":0,"expiration":"1970-01-01T00:00:0","operations":[["account_update",{"account":"son-account","active":{"weight_threshold":1,"account_auths":[["sonaccount01",1],["sonaccount02",1],["sonaccount03",1],["sonaccount04",1],["sonaccount05",1],["sonaccount06",1],["sonaccount07",1],["sonaccount08",1],["sonaccount09",1],["sonaccount10",1],["sonaccount11",1],["sonaccount12",1],["sonaccount13",1],["sonaccount14",1],["sonaccount15",1]],"key_auths":[]},"memo_key":"TST78bZV5JsuNKUVM7WDVKBnuiuXBTR8gsPEaev2fj96iXqq5R13u","json_metadata":""}]],"extensions":[]} false - htrx.set_reference_block(block_id_type("0000d68fd4d7abb7e8975398b9e93f93db990ac8")); - htrx.set_expiration(fc::time_point::from_iso_string("2021-03-23T19:21:24")); - // temp - ilog("TRX: ${htrx}", ("htrx", htrx)); - ilog("EXP: {\"ref_block_num\":54927,\"ref_block_prefix\":3081492436,\"expiration\":\"2021-03-23T19:21:24\",\"operations\":[{\"type\":\"account_update_operation\",\"value\":{\"account\":\"son-account\",\"active\":{\"weight_threshold\":1,\"account_auths\":[[\"sonaccount01\",1],[\"sonaccount02\",1],[\"sonaccount03\",1],[\"sonaccount04\",1],[\"sonaccount05\",1],[\"sonaccount06\",1],[\"sonaccount07\",1],[\"sonaccount08\",1],[\"sonaccount09\",1],[\"sonaccount10\",1],[\"sonaccount11\",1],[\"sonaccount12\",1],[\"sonaccount13\",1],[\"sonaccount14\",1],[\"sonaccount15\",1]],\"key_auths\":[]},\"memo_key\":\"TST1111111111111111111111111111111114T1Anm\",\"json_metadata\":\"\"}}],\"extensions\":[],\"signatures\":[\"1f323561e46aa7703850d6afc5fdf00b338424eed695c9513568135bb5dbc051f3242a463f29d17257d982ae616214239b5405073ae7771469a7ea9e36c1577c45\"]}"); std::string chain_id_str = node_rpc_client->get_chain_id(); const hive::chain_id_type chain_id(chain_id_str); @@ -458,13 +457,11 @@ std::string sidechain_net_handler_hive::process_sidechain_transaction(const side signature_type st = htrx.sign(*privkey, chain_id); ilog("TRX: ${htrx}", ("htrx", htrx)); - ilog("EXP: {\"ref_block_num\":54927,\"ref_block_prefix\":3081492436,\"expiration\":\"2021-03-23T19:21:24\",\"operations\":[{\"type\":\"account_update_operation\",\"value\":{\"account\":\"son-account\",\"active\":{\"weight_threshold\":1,\"account_auths\":[[\"sonaccount01\",1],[\"sonaccount02\",1],[\"sonaccount03\",1],[\"sonaccount04\",1],[\"sonaccount05\",1],[\"sonaccount06\",1],[\"sonaccount07\",1],[\"sonaccount08\",1],[\"sonaccount09\",1],[\"sonaccount10\",1],[\"sonaccount11\",1],[\"sonaccount12\",1],[\"sonaccount13\",1],[\"sonaccount14\",1],[\"sonaccount15\",1]],\"key_auths\":[]},\"memo_key\":\"TST1111111111111111111111111111111114T1Anm\",\"json_metadata\":\"\"}}],\"extensions\":[],\"signatures\":[\"1f323561e46aa7703850d6afc5fdf00b338424eed695c9513568135bb5dbc051f3242a463f29d17257d982ae616214239b5405073ae7771469a7ea9e36c1577c45\"]}"); std::stringstream ss_st; fc::raw::pack(ss_st, st, 1000); std::string st_str = boost::algorithm::hex(ss_st.str()); - st_str = ""; return st_str; } @@ -484,6 +481,10 @@ std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidecha } ilog("HTRX: ${htrx}", ("htrx", htrx)); + std::string params = fc::json::to_string(htrx); + ilog("HTRX: ${htrx}", ("htrx", params)); + node_rpc_client->network_broadcast_api_broadcast_transaction(params); + // try { // trx.validate(); // database.push_transaction(trx, database::validation_steps::skip_block_size_check); -- 2.45.2 From 944fa3b072c3ae4d0bca24d1d4195853be8e353c Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 31 Mar 2021 12:28:41 +0200 Subject: [PATCH 07/57] Tx ID calculation on broadcasting Hive transaction --- .../peerplays_sidechain/hive/transaction.cpp | 13 +++++++++++++ .../peerplays_sidechain/hive/transaction.hpp | 2 ++ .../graphene/peerplays_sidechain/hive/types.hpp | 2 +- .../sidechain_net_handler_hive.cpp | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp index 6b2da082..a5c8bcfd 100644 --- a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp @@ -7,6 +7,19 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { +digest_type transaction::digest() const { + digest_type::encoder enc; + fc::raw::pack(enc, *this); + return enc.result(); +} + +transaction_id_type transaction::id() const { + auto h = digest(); + transaction_id_type result; + memcpy(result._hash, h._hash, std::min(sizeof(result), sizeof(h))); + return result; +} + digest_type transaction::sig_digest(const chain_id_type &chain_id) const { digest_type::encoder enc; fc::raw::pack(enc, chain_id); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp index 6d1de526..8b35b7b3 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp @@ -17,6 +17,8 @@ struct transaction { std::vector operations; extensions_type extensions; + digest_type digest() const; + transaction_id_type id() const; digest_type sig_digest(const chain_id_type &chain_id) const; void set_expiration(fc::time_point_sec expiration_time); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp index 13bf80fe..e49556d3 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -15,7 +15,7 @@ typedef fc::sha256 chain_id_type; typedef std::string account_name_type; typedef fc::ripemd160 block_id_type; //typedef fc::ripemd160 checksum_type; -//typedef fc::ripemd160 transaction_id_type; +typedef fc::ripemd160 transaction_id_type; typedef fc::sha256 digest_type; typedef fc::ecc::compact_signature signature_type; //typedef safe share_type; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index d5bd1a39..6db743b7 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -496,7 +496,7 @@ std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidecha // return ""; // } - return ""; + return htrx.id().str(); } int64_t sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_transaction_object &sto) { -- 2.45.2 From 2c5e1c35a52b1426d9e1936f8e5c6602a4b7b158 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Fri, 2 Apr 2021 15:02:46 +0200 Subject: [PATCH 08/57] add_sidechain_address fixes for HIVE, wallet doc fixes --- .../chain/sidechain_address_evaluator.cpp | 8 +-- .../wallet/include/graphene/wallet/wallet.hpp | 52 +++++++++++++------ libraries/wallet/wallet.cpp | 5 +- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/libraries/chain/sidechain_address_evaluator.cpp b/libraries/chain/sidechain_address_evaluator.cpp index ae802627..625ef2f0 100644 --- a/libraries/chain/sidechain_address_evaluator.cpp +++ b/libraries/chain/sidechain_address_evaluator.cpp @@ -9,7 +9,9 @@ namespace graphene { namespace chain { void_result add_sidechain_address_evaluator::do_evaluate(const sidechain_address_add_operation& op) { try{ - FC_ASSERT( op.deposit_public_key.length() > 0 && op.deposit_address.length() == 0 && op.deposit_address_data.length() == 0, "User should add a valid deposit public key and a null deposit address"); + if (op.sidechain == sidechain_type::bitcoin) { + FC_ASSERT( op.deposit_public_key.length() > 0 && op.deposit_address.length() == 0 && op.deposit_address_data.length() == 0, "ser should add a valid deposit public key and a null deposit address (Bitcoin only)"); + } const auto& sdpke_idx = db().get_index_type().indices().get(); FC_ASSERT( sdpke_idx.find(boost::make_tuple(op.sidechain, op.deposit_public_key, time_point_sec::maximum())) == sdpke_idx.end(), "An active deposit key already exists" ); return void_result(); @@ -31,8 +33,8 @@ object_id_type add_sidechain_address_evaluator::do_apply(const sidechain_address obj.sidechain_address_account = op.sidechain_address_account; obj.sidechain = op.sidechain; obj.deposit_public_key = op.deposit_public_key; - obj.deposit_address = ""; - obj.deposit_address_data = ""; + obj.deposit_address = op.deposit_address; + obj.deposit_address_data = op.deposit_address_data; obj.withdraw_public_key = op.withdraw_public_key; obj.withdraw_address = op.withdraw_address; obj.valid_from = db().head_block_time(); diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index b09d950e..afaa49d4 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -651,7 +651,7 @@ class wallet_api * @see suggest_brain_key() * * @param brain_key Brain key - * @param numberOfDesiredKeys Number of desired keys + * @param number_of_desired_keys Number of desired keys * @return A list of keys that are deterministically derived from the brainkey */ vector derive_owner_keys_from_brain_key(string brain_key, int number_of_desired_keys = 1) const; @@ -666,7 +666,12 @@ class wallet_api bool is_public_key_registered(string public_key) const; /** - * @param role - active | owner | memo + * Gets private key from password + * + * @param account Account name + * @param role Account role - active | owner | memo + * @param password Account password + * @return public/private key pair */ pair get_private_key_from_password( string account, string role, string password )const; @@ -894,18 +899,24 @@ class wallet_api * that it exists in the blockchain. If it exists then it will report the amount received and * who sent it. * - * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from * @param confirmation_receipt - a base58 encoded stealth confirmation + * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from + * @param opt_memo - optional memo */ blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); /** - * Transfers a public balance from @from to one or more blinded balances using a + * Transfers a public balance from from_account_id_or_name to one or more blinded balances using a * stealth transfer. + * + * @param from_account_id_or_name account id or name + * @param asset_symbol asset symbol + * @param to_amounts map from key or label to amount + * @param broadcast true to broadcast the transaction on the network + * @returns blind confirmation structure */ blind_confirmation transfer_to_blind( string from_account_id_or_name, string asset_symbol, - /** map from key or label to amount */ vector> to_amounts, bool broadcast = false ); @@ -1009,11 +1020,11 @@ class wallet_api * * @param buyer_account The account buying the asset for another asset. * @param base The name or id of the asset to buy. - * @param quote The name or id of the assest being offered as payment. + * @param quote The name or id of the asset being offered as payment. * @param rate The rate in base:quote at which you want to buy. * @param amount the amount of base you want to buy. * @param broadcast true to broadcast the transaction on the network. - * @param The signed transaction selling the funds. + * @returns The signed transaction buying the funds. */ signed_transaction buy( string buyer_account, string base, @@ -1493,6 +1504,7 @@ class wallet_api * @param account the name or id of the account who owns the address * @param sidechain a sidechain to whom address belongs * @param deposit_public_key sidechain public key used for deposit address + * @param deposit_address sidechain address for deposits * @param withdraw_public_key sidechain public key used for withdraw address * @param withdraw_address sidechain address for withdrawals * @param broadcast true to broadcast the transaction on the network @@ -1501,6 +1513,7 @@ class wallet_api signed_transaction add_sidechain_address(string account, sidechain_type sidechain, string deposit_public_key, + string deposit_address, string withdraw_public_key, string withdraw_address, bool broadcast = false); @@ -1561,7 +1574,7 @@ class wallet_api /** * Update a witness object owned by the given account. * - * @param witness The name of the witness's owner account. Also accepts the ID of the owner account or the ID of the witness. + * @param witness_name The name of the witness's owner account. Also accepts the ID of the owner account or the ID of the witness. * @param url Same as for create_witness. The empty string makes it remain the same. * @param block_signing_key The new block signing public key. The empty string makes it remain the same. * @param broadcast true if you wish to broadcast the transaction. @@ -1599,7 +1612,7 @@ class wallet_api * Update your votes for a worker * * @param account The account which will pay the fee and update votes. - * @param worker_vote_delta {"vote_for" : [...], "vote_against" : [...], "vote_abstain" : [...]} + * @param delta {"vote_for" : [...], "vote_against" : [...], "vote_abstain" : [...]} * @param broadcast true if you wish to broadcast the transaction. */ signed_transaction update_worker_votes( @@ -1732,7 +1745,7 @@ class wallet_api signed_transaction update_son_votes(string voting_account, std::vector sons_to_approve, std::vector sons_to_reject, - uint16_t desired_number_of_son, + uint16_t desired_number_of_sons, bool broadcast = false); /** Vote for a given witness. @@ -1826,8 +1839,8 @@ class wallet_api * set, your preferences will be ignored. * * @param account_to_modify the name or id of the account to update - * @param number_of_committee_members the number - * + * @param desired_number_of_witnesses desired number of witnesses + * @param desired_number_of_committee_members desired number of committee members * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote proxy settings */ @@ -1958,6 +1971,7 @@ class wallet_api /** Get random numbers * @brief Returns the random number + * @param account The account paying the fee to get a random number * @param minimum Lower bound of segment containing random number * @param maximum Upper bound of segment containing random number * @param selections Number of random numbers to return @@ -1975,7 +1989,9 @@ class wallet_api /** Get random number * @brief Returns the random number + * @param account The account paying the fee to get a random number * @param bound Upper bound of segment containing random number + * @param broadcast true if you wish to broadcast the transaction * @return Random number from segment [0, bound) */ uint64_t get_random_number(string account, @@ -2155,6 +2171,7 @@ class wallet_api /** Creates a new tournament * @param creator the accout that is paying the fee to create the tournament * @param options the options detailing the specifics of the tournament + * @param broadcast true if you wish to broadcast the transaction * @return the signed version of the transaction */ signed_transaction tournament_create( string creator, tournament_options options, bool broadcast = false ); @@ -2194,7 +2211,7 @@ class wallet_api tournament_state state); /** Get specific information about a tournament - * @param tournament_id the ID of the tournament + * @param id the ID of the tournament */ tournament_object get_tournament(tournament_id_type id); @@ -2202,6 +2219,7 @@ class wallet_api * @param game_id the id of the game * @param player_account the name of the player * @param gesture rock, paper, or scissors + * @param broadcast true if you wish to broadcast the transaction * @return the signed version of the transaction */ signed_transaction rps_throw(game_id_type game_id, @@ -2254,6 +2272,9 @@ class wallet_api * @param revenue_split revenue split for the sale * @param is_transferable can transfer the NFT or not * @param is_sellable can sell NFT or not + * @param role_id account role id + * @param max_supply max supply of NTFs + * @param lottery_options lottery options * @param broadcast true to broadcast transaction to the network * @return Signed transaction transfering the funds */ @@ -2281,6 +2302,7 @@ class wallet_api * @param revenue_split revenue split for the sale * @param is_transferable can transfer the NFT or not * @param is_sellable can sell NFT or not + * @param role_id account role id * @param broadcast true to broadcast transaction to the network * @return Signed transaction transfering the funds */ @@ -2394,8 +2416,8 @@ class wallet_api /** * @brief Returns operator approved state for all NFT owned by owner - * @param owner NFT owner account ID - * @param token_id NFT ID + * @param owner_account_id_or_name NFT owner account ID or name + * @param operator_account_id_or_name NFT operator account ID or name * @return True if operator is approved for all NFT owned by owner, else False */ bool nft_is_approved_for_all(string owner_account_id_or_name, string operator_account_id_or_name) const; diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 29306675..13d1915a 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2221,6 +2221,7 @@ public: signed_transaction add_sidechain_address(string account, sidechain_type sidechain, string deposit_public_key, + string deposit_address, string withdraw_public_key, string withdraw_address, bool broadcast /* = false */) @@ -2232,6 +2233,7 @@ public: op.sidechain_address_account = sidechain_address_account_id; op.sidechain = sidechain; op.deposit_public_key = deposit_public_key; + op.deposit_address = deposit_address; op.withdraw_public_key = withdraw_public_key; op.withdraw_address = withdraw_address; @@ -5086,11 +5088,12 @@ vector> wallet_api::get_son_wallets(uint32_t limit) signed_transaction wallet_api::add_sidechain_address(string account, sidechain_type sidechain, string deposit_public_key, + string deposit_address, string withdraw_public_key, string withdraw_address, bool broadcast /* = false */) { - return my->add_sidechain_address(account, sidechain, deposit_public_key, withdraw_public_key, withdraw_address, broadcast); + return my->add_sidechain_address(account, sidechain, deposit_public_key, deposit_address, withdraw_public_key, withdraw_address, broadcast); } signed_transaction wallet_api::delete_sidechain_address(string account, -- 2.45.2 From df125c9a0b381f2d9c38ecaa808b3f6665877764 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 6 Apr 2021 15:32:55 +0200 Subject: [PATCH 09/57] SON for HIVE hardfork and assets --- libraries/chain/db_maint.cpp | 78 +++++++++++++++++++ libraries/chain/hardfork.d/SON_FOR_HIVE.hf | 4 + .../chain/protocol/chain_parameters.hpp | 10 +++ 3 files changed, 92 insertions(+) create mode 100644 libraries/chain/hardfork.d/SON_FOR_HIVE.hf diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index d695bb0f..14bf6ead 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1929,6 +1929,80 @@ void database::perform_son_tasks() gpo.pending_parameters->extensions.value.btc_asset = btc_asset.get_id(); }); } + // create HBD asset here because son_account is the issuer of the HBD + if (gpo.parameters.hbd_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_FOR_HIVE_TIME) + { + const asset_dynamic_data_object& dyn_asset = + create([](asset_dynamic_data_object& a) { + a.current_supply = 0; + }); + + const asset_object& hbd_asset = + create( [&gpo, &dyn_asset]( asset_object& a ) { + a.symbol = "HBD"; + a.precision = 3; + a.issuer = gpo.parameters.son_account(); + a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + a.options.market_fee_percent = 500; // 5% + a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; + a.options.flags = asset_issuer_permission_flags::charge_market_fee | + //asset_issuer_permission_flags::white_list | + asset_issuer_permission_flags::override_authority | + asset_issuer_permission_flags::transfer_restricted | + asset_issuer_permission_flags::disable_confidential; + a.options.core_exchange_rate.base.amount = 100000; + a.options.core_exchange_rate.base.asset_id = asset_id_type(0); + a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value + a.options.core_exchange_rate.quote.asset_id = a.id; + a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty + a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set + a.options.whitelist_markets.clear(); // might be traded with + a.options.blacklist_markets.clear(); // might not be traded with + a.dynamic_asset_data_id = dyn_asset.id; + }); + modify( gpo, [&hbd_asset]( global_property_object& gpo ) { + gpo.parameters.extensions.value.hbd_asset = hbd_asset.get_id(); + if( gpo.pending_parameters ) + gpo.pending_parameters->extensions.value.hbd_asset = hbd_asset.get_id(); + }); + } + // create HIVE asset here because son_account is the issuer of the HIVE + if (gpo.parameters.hive_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_TIME) + { + const asset_dynamic_data_object& dyn_asset = + create([](asset_dynamic_data_object& a) { + a.current_supply = 0; + }); + + const asset_object& hive_asset = + create( [&gpo, &dyn_asset]( asset_object& a ) { + a.symbol = "HIVE"; + a.precision = 8; + a.issuer = gpo.parameters.son_account(); + a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + a.options.market_fee_percent = 500; // 5% + a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; + a.options.flags = asset_issuer_permission_flags::charge_market_fee | + //asset_issuer_permission_flags::white_list | + asset_issuer_permission_flags::override_authority | + asset_issuer_permission_flags::transfer_restricted | + asset_issuer_permission_flags::disable_confidential; + a.options.core_exchange_rate.base.amount = 100000; + a.options.core_exchange_rate.base.asset_id = asset_id_type(0); + a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value + a.options.core_exchange_rate.quote.asset_id = a.id; + a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty + a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set + a.options.whitelist_markets.clear(); // might be traded with + a.options.blacklist_markets.clear(); // might not be traded with + a.dynamic_asset_data_id = dyn_asset.id; + }); + modify( gpo, [&hive_asset]( global_property_object& gpo ) { + gpo.parameters.extensions.value.hive_asset = hive_asset.get_id(); + if( gpo.pending_parameters ) + gpo.pending_parameters->extensions.value.hive_asset = hive_asset.get_id(); + }); + } // Pay the SONs if (head_block_time() >= HARDFORK_SON_TIME) { @@ -2157,6 +2231,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g p.pending_parameters->extensions.value.btc_asset = p.parameters.extensions.value.btc_asset; if( !p.pending_parameters->extensions.value.maximum_son_count.valid() ) p.pending_parameters->extensions.value.maximum_son_count = p.parameters.extensions.value.maximum_son_count; + if( !p.pending_parameters->extensions.value.hbd_asset.valid() ) + p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset; + if( !p.pending_parameters->extensions.value.hive_asset.valid() ) + p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset; p.parameters = std::move(*p.pending_parameters); p.pending_parameters.reset(); } diff --git a/libraries/chain/hardfork.d/SON_FOR_HIVE.hf b/libraries/chain/hardfork.d/SON_FOR_HIVE.hf new file mode 100644 index 00000000..76ba2b56 --- /dev/null +++ b/libraries/chain/hardfork.d/SON_FOR_HIVE.hf @@ -0,0 +1,4 @@ +// Wednesday, March 31, 2021 0:00:00 +#ifndef HARDFORK_SON_FOR_HIVE_TIME +#define HARDFORK_SON_FOR_HIVE_TIME (fc::time_point_sec( 1617148800 )) +#endif diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index c24a0576..3a11e99f 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -68,6 +68,8 @@ namespace graphene { namespace chain { optional < account_id_type > son_account = GRAPHENE_NULL_ACCOUNT; optional < asset_id_type > btc_asset = asset_id_type(); optional < uint16_t > maximum_son_count = GRAPHENE_DEFAULT_MAX_SONS; ///< maximum number of active SONS + optional < asset_id_type > hbd_asset = asset_id_type(); + optional < asset_id_type > hive_asset = asset_id_type(); }; struct chain_parameters @@ -212,6 +214,12 @@ namespace graphene { namespace chain { inline uint16_t maximum_son_count()const { return extensions.value.maximum_son_count.valid() ? *extensions.value.maximum_son_count : GRAPHENE_DEFAULT_MAX_SONS; } + inline asset_id_type hbd_asset() const { + return extensions.value.hbd_asset.valid() ? *extensions.value.hbd_asset : asset_id_type(); + } + inline asset_id_type hive_asset() const { + return extensions.value.hive_asset.valid() ? *extensions.value.hive_asset : asset_id_type(); + } private: static void safe_copy(chain_parameters& to, const chain_parameters& from); }; @@ -247,6 +255,8 @@ FC_REFLECT( graphene::chain::parameter_extension, (son_account) (btc_asset) (maximum_son_count) + (hbd_asset) + (hive_asset) ) FC_REFLECT( graphene::chain::chain_parameters, -- 2.45.2 From daa4fa089a986838ea5a56a6035546bae95e8901 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Thu, 8 Apr 2021 12:08:28 +0200 Subject: [PATCH 10/57] Deposit detection and deposit object created --- .../sidechain_net_handler_hive.hpp | 2 + .../sidechain_net_handler_hive.cpp | 188 +++++++++--------- 2 files changed, 96 insertions(+), 94 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index cb9a1f81..6dd19749 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -16,7 +16,9 @@ class hive_node_rpc_client : public rpc_client { public: hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); + std::string account_history_api_get_transaction(std::string transaction_id); std::string block_api_get_block(uint32_t block_number); + std::string condenser_api_get_transaction(std::string transaction_id); std::string database_api_get_dynamic_global_properties(); std::string database_api_get_version(); std::string network_broadcast_api_broadcast_transaction(std::string htrx); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 6db743b7..e0582feb 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -31,11 +31,21 @@ hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std: rpc_client(_ip, _port, _user, _password) { } +std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { + std::string params = "{ \"id\": \"" + transaction_id + "\" }"; + return send_post_request("account_history_api.get_transaction", params, false); +} + std::string hive_node_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, false); } +std::string hive_node_rpc_client::condenser_api_get_transaction(std::string transaction_id) { + std::string params = "[\"" + transaction_id + "\"]"; + return send_post_request("condenser_api.get_transaction", params, false); +} + std::string hive_node_rpc_client::database_api_get_dynamic_global_properties() { return send_post_request("database_api.get_dynamic_global_properties", "", false); } @@ -349,41 +359,40 @@ void sidechain_net_handler_hive::process_primary_wallet() { } void sidechain_net_handler_hive::process_sidechain_addresses() { - // const auto &sidechain_addresses_idx = database.get_index_type(); - // const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get(); - // 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; + const auto &sidechain_addresses_idx = database.get_index_type(); + const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get(); + 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; + }); } bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object &swdo) { @@ -485,17 +494,6 @@ std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidecha ilog("HTRX: ${htrx}", ("htrx", params)); node_rpc_client->network_broadcast_api_broadcast_transaction(params); - // 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 htrx.id().str(); } @@ -543,64 +541,66 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { boost::property_tree::ptree block_json; boost::property_tree::read_json(ss, block_json); - for (const auto &tx_child : block_json.get_child("result.block.transactions")) { - const auto &tx = tx_child.second; + for (const auto &tx_ids_child : block_json.get_child("result.block.transaction_ids")) { + const auto &transaction_id = tx_ids_child.second.get_value(); - for (const auto &ops : tx.get_child("operations")) { - const auto &op = ops.second; + std::string tx_str = node_rpc_client->account_history_api_get_transaction(transaction_id); + if (tx_str != "") { - std::string operation_type = op.get("type"); - ilog("Transactions: ${operation_type}", ("operation_type", operation_type)); + std::stringstream ss_tx(tx_str); + boost::property_tree::ptree tx; + boost::property_tree::read_json(ss_tx, tx); - if (operation_type == "transfer_operation") { - const auto &op_value = op.get_child("value"); + size_t operation_index = -1; + for (const auto &ops : tx.get_child("result.operations")) { + const auto &op = ops.second; + operation_index = operation_index + 1; - std::string from = op_value.get("from"); - std::string to = op_value.get("to"); + std::string operation_type = op.get("type"); - const auto &amount_child = op_value.get_child("amount"); + if (operation_type == "transfer_operation") { + const auto &op_value = op.get_child("value"); - uint64_t amount = amount_child.get("amount"); - uint64_t precision = amount_child.get("precision"); - std::string nai = amount_child.get("nai"); + std::string from = op_value.get("from"); + std::string to = op_value.get("to"); - ilog("Transfer from ${from} to ${to}, amount ${amount}, precision ${precision}, nai ${nai}", - ("from", from)("to", to)("amount", amount)("precision", precision)("nai", nai)); + const auto &amount_child = op_value.get_child("amount"); + + uint64_t amount = amount_child.get("amount"); + uint64_t precision = amount_child.get("precision"); + std::string nai = amount_child.get("nai"); + + if (to == "son-account") { + const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum())); + if (addr_itr == sidechain_addresses_idx.end()) + continue; + + std::stringstream ss; + ss << "hive" + << "-" << transaction_id << "-" << 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 = addr_itr->sidechain; + sed.sidechain_uid = sidechain_uid; + sed.sidechain_transaction_id = transaction_id; + sed.sidechain_from = from; + sed.sidechain_to = to; + sed.sidechain_currency = "HIVE"; + sed.sidechain_amount = amount; + sed.peerplays_from = addr_itr->sidechain_address_account; + sed.peerplays_to = database.get_global_properties().parameters.son_account(); + price hive_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; + sed.peerplays_asset = asset(sed.sidechain_amount * hive_price.base.amount / hive_price.quote.amount); + sidechain_event_data_received(sed); + } + } } } } - - //const auto &vins = extract_info_from_block(block); - - //const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - - /*for (const auto &v : vins) { - // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address, time_point_sec::maximum())); - if (addr_itr == sidechain_addresses_idx.end()) - continue; - - std::stringstream ss; - ss << "bitcoin" - << "-" << v.out.hash_tx << "-" << v.out.n_vout; - 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 = addr_itr->sidechain; - sed.sidechain_uid = sidechain_uid; - sed.sidechain_transaction_id = v.out.hash_tx; - sed.sidechain_from = ""; - sed.sidechain_to = v.address; - sed.sidechain_currency = "BTC"; - sed.sidechain_amount = v.out.amount; - sed.peerplays_from = addr_itr->sidechain_address_account; - sed.peerplays_to = database.get_global_properties().parameters.son_account(); - price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; - sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount); - sidechain_event_data_received(sed); - }*/ } } -- 2.45.2 From 1f53359248b7c9f31f2805dd14ada62d538a6d0d Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 13 Apr 2021 23:04:53 +0200 Subject: [PATCH 11/57] Deposit processing for Hive assets HBD and HIVE --- .../sidechain_net_handler.cpp | 30 +- .../sidechain_net_handler_bitcoin.cpp | 8 +- .../sidechain_net_handler_hive.cpp | 267 ++++++++++-------- 3 files changed, 167 insertions(+), 138 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 28c44397..b934c246 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -161,21 +161,25 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ const chain::global_property_object &gpo = database.get_global_properties(); - asset_id_type btc_asset_id = database.get_global_properties().parameters.btc_asset(); - std::string btc_asset_id_str = fc::to_string(btc_asset_id.space_id) + "." + - fc::to_string(btc_asset_id.type_id) + "." + - fc::to_string((uint64_t)btc_asset_id.instance); - + bool enable_peerplays_asset_deposits = false; #ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS - // Accepts BTC and peerplays asset deposits - bool deposit_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) != 0)); - bool withdraw_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) == 0)); -#else - // Accepts BTC deposits only - bool deposit_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare("BTC") == 0)); - bool withdraw_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) == 0)); + enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) && + (sed.sidechain_currency.compare("BTC") != 0) && + (sed.sidechain_currency.compare("HBD") != 0) && + (sed.sidechain_currency.compare("HIVE") != 0); #endif + bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) && + (((sed.sidechain == sidechain_type::bitcoin) && (sed.sidechain_currency.compare("BTC") == 0)) || + ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HBD") == 0)) || + ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) || + enable_peerplays_asset_deposits); + + bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) && + ((sed.sidechain_currency.compare("BTC") == 0) || + (sed.sidechain_currency.compare("HBD") == 0) || + (sed.sidechain_currency.compare("HIVE") == 0)); + // Deposit request if (deposit_condition) { @@ -379,7 +383,7 @@ void sidechain_net_handler::process_deposits() { } //Ignore the deposits which are not valid anymore, considered refunds. const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_to, time_point_sec::maximum())); + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_from, time_point_sec::maximum())); if (addr_itr == sidechain_addresses_idx.end()) { return; } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 2cf8b68a..adb9182c 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1094,7 +1094,7 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) if (swdo != idx.end()) { std::string swdo_txid = swdo->sidechain_transaction_id; - std::string swdo_address = swdo->sidechain_to; + std::string swdo_address = swdo->sidechain_from; uint64_t swdo_amount = swdo->sidechain_amount.value; uint64_t swdo_vout = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1)); @@ -1611,7 +1611,7 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_ return ""; } //Get redeem script for deposit address - std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_to); + std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_from); std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second; std::stringstream ss(pw_address_json); @@ -1803,8 +1803,8 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) sed.sidechain = addr_itr->sidechain; sed.sidechain_uid = sidechain_uid; sed.sidechain_transaction_id = v.out.hash_tx; - sed.sidechain_from = ""; - sed.sidechain_to = v.address; + sed.sidechain_from = v.address; + sed.sidechain_to = ""; sed.sidechain_currency = "BTC"; sed.sidechain_amount = v.out.amount; sed.peerplays_from = addr_itr->sidechain_address_account; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index e0582feb..2634dc37 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -25,7 +25,8 @@ #include #include -namespace graphene { namespace peerplays_sidechain { +namespace graphene { +namespace peerplays_sidechain { hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : rpc_client(_ip, _port, _user, _password) { @@ -195,73 +196,95 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { 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::value: { - // should_approve = false; - // break; - // } - // - // case chain::operation::tag::value: { - // son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; - // const auto &idx = database.get_index_type().indices().get(); - // 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(); - // - // asset sidechain_asset = asset(swdo->sidechain_amount, fc::variant(swdo->sidechain_currency, 1).as(1)); - // price sidechain_asset_price = database.get(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::value: { - // should_approve = false; - // break; - // } - // - // case chain::operation::tag::value: { - // should_approve = true; - // break; - // } - // - // default: - // should_approve = false; - // elog("=================================================="); - // elog("Proposal not considered for approval ${po}", ("po", po)); - // elog("=================================================="); - // } + //const chain::global_property_object &gpo = database.get_global_properties(); - should_approve = true; + 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::value: { + should_approve = true; + break; + } + + case chain::operation::tag::value: { + bool process_ok = false; + son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(swdo_id); + if (swdo != idx.end()) { + + std::string swdo_txid = swdo->sidechain_transaction_id; + std::string swdo_sidechain_from = swdo->sidechain_from; + std::string swdo_sidechain_currency = swdo->sidechain_currency; + uint64_t swdo_sidechain_amount = swdo->sidechain_amount.value; + uint64_t swdo_op_idx = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-"))); + + std::string tx_str = node_rpc_client->account_history_api_get_transaction(swdo_txid); + if (tx_str != "") { + + std::stringstream ss_tx(tx_str); + boost::property_tree::ptree tx; + boost::property_tree::read_json(ss_tx, tx); + + uint64_t op_idx = -1; + for (const auto &ops : tx.get_child("result.operations")) { + const auto &op = ops.second; + op_idx = op_idx + 1; + if (op_idx == swdo_op_idx) { + std::string operation_type = op.get("type"); + + if (operation_type == "transfer_operation") { + const auto &op_value = op.get_child("value"); + + std::string address = op_value.get("from"); + + const auto &amount_child = op_value.get_child("amount"); + + uint64_t amount = amount_child.get("amount"); + std::string nai = amount_child.get("nai"); + std::string sidechain_currency = ""; + if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) { + sidechain_currency = "HBD"; + } + if ((nai == "@@000000021") /*?? HIVE*/ || (nai == "@@000000021" /*TESTS*/)) { + sidechain_currency = "HIVE"; + } + + process_ok = (swdo_sidechain_from == address) && + (swdo_sidechain_currency == sidechain_currency) && + (swdo_sidechain_amount == amount); + } + } + } + } + } + should_approve = process_ok; + break; + } + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + default: + should_approve = false; + elog("=================================================="); + elog("Proposal not considered for approval ${po}", ("po", po)); + elog("=================================================="); + } return should_approve; } @@ -397,53 +420,48 @@ void sidechain_net_handler_hive::process_sidechain_addresses() { 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(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; - // } - // } + const chain::global_property_object &gpo = database.get_global_properties(); + + price asset_price; + asset asset_to_issue; + if (swdo.sidechain_currency == "HBD") { + asset_price = database.get(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate; + asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, database.get_global_properties().parameters.hbd_asset()); + } + if (swdo.sidechain_currency == "HIVE") { + asset_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; + asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, database.get_global_properties().parameters.hive_asset()); + } + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + 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); + + son_wallet_deposit_process_operation swdp_op; + swdp_op.payer = gpo.parameters.son_account(); + swdp_op.son_wallet_deposit_id = swdo.id; + proposal_op.proposed_ops.emplace_back(swdp_op); + + asset_issue_operation ai_op; + ai_op.fee = asset(2001000); + ai_op.issuer = gpo.parameters.son_account(); + ai_op.asset_to_issue = asset_to_issue; + ai_op.issue_to_account = swdo.peerplays_from; + proposal_op.proposed_ops.emplace_back(ai_op); + + 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; } @@ -551,10 +569,10 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { boost::property_tree::ptree tx; boost::property_tree::read_json(ss_tx, tx); - size_t operation_index = -1; + size_t op_idx = -1; for (const auto &ops : tx.get_child("result.operations")) { const auto &op = ops.second; - operation_index = operation_index + 1; + op_idx = op_idx + 1; std::string operation_type = op.get("type"); @@ -567,8 +585,15 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { const auto &amount_child = op_value.get_child("amount"); uint64_t amount = amount_child.get("amount"); - uint64_t precision = amount_child.get("precision"); + //uint64_t precision = amount_child.get("precision"); std::string nai = amount_child.get("nai"); + std::string sidechain_currency = ""; + if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) { + sidechain_currency = "HBD"; + } + if ((nai == "@@000000021") /*?? HIVE*/ || (nai == "@@000000021" /*TESTS*/)) { + sidechain_currency = "HIVE"; + } if (to == "son-account") { const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); @@ -578,7 +603,7 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { std::stringstream ss; ss << "hive" - << "-" << transaction_id << "-" << operation_index; + << "-" << transaction_id << "-" << op_idx; std::string sidechain_uid = ss.str(); sidechain_event_data sed; @@ -589,7 +614,7 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { sed.sidechain_transaction_id = transaction_id; sed.sidechain_from = from; sed.sidechain_to = to; - sed.sidechain_currency = "HIVE"; + sed.sidechain_currency = sidechain_currency; sed.sidechain_amount = amount; sed.peerplays_from = addr_itr->sidechain_address_account; sed.peerplays_to = database.get_global_properties().parameters.son_account(); @@ -639,5 +664,5 @@ void sidechain_net_handler_hive::on_applied_block(const signed_block &b) { // } // } } - -}} // namespace graphene::peerplays_sidechain +} +} // namespace graphene::peerplays_sidechain -- 2.45.2 From 876655fb39f273c9cf56184cd13461cb796ec12d Mon Sep 17 00:00:00 2001 From: serkixenos Date: Fri, 16 Apr 2021 00:30:29 +0200 Subject: [PATCH 12/57] Quickfix: Approve Hive transaction signing --- .../peerplays_sidechain/sidechain_net_handler_hive.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 2634dc37..25b4b3e1 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -274,6 +274,11 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { break; } + case chain::operation::tag::value: { + should_approve = true; + break; + } + case chain::operation::tag::value: { should_approve = true; break; -- 2.45.2 From dfcc66a7d0162cf0ba58b96ccaf2892205fb4c2f Mon Sep 17 00:00:00 2001 From: serkixenos Date: Fri, 16 Apr 2021 01:08:19 +0200 Subject: [PATCH 13/57] Quickfix: Fix HIVE asset precision --- libraries/chain/db_maint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 14bf6ead..98e988e9 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1977,7 +1977,7 @@ void database::perform_son_tasks() const asset_object& hive_asset = create( [&gpo, &dyn_asset]( asset_object& a ) { a.symbol = "HIVE"; - a.precision = 8; + a.precision = 3; a.issuer = gpo.parameters.son_account(); a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; a.options.market_fee_percent = 500; // 5% -- 2.45.2 From 7536f1a2d7bf07881c1b4da05f4e3ac9f2bb3a62 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Thu, 22 Apr 2021 11:35:29 +0200 Subject: [PATCH 14/57] Withdrawal payment detection --- .../peerplays_sidechain/CMakeLists.txt | 1 + .../peerplays_sidechain/common/utils.cpp | 15 +++++ .../peerplays_sidechain/hive/operations.cpp | 10 ++-- .../peerplays_sidechain/common/utils.hpp | 6 ++ .../sidechain_net_handler.hpp | 4 ++ .../sidechain_net_handler_hive.hpp | 2 - .../sidechain_net_handler_peerplays.hpp | 1 - .../sidechain_net_manager.hpp | 2 + .../sidechain_net_handler.cpp | 56 +++++++++++++++++++ .../sidechain_net_handler_bitcoin.cpp | 1 + .../sidechain_net_handler_hive.cpp | 49 +++------------- .../sidechain_net_handler_peerplays.cpp | 49 +++------------- .../sidechain_net_manager.cpp | 7 +++ 13 files changed, 114 insertions(+), 89 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/common/utils.cpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index ca0f56ef..60eb03c8 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -15,6 +15,7 @@ add_library( peerplays_sidechain bitcoin/utils.cpp bitcoin/sign_bitcoin_transaction.cpp common/rpc_client.cpp + common/utils.cpp hive/operations.cpp hive/transaction.cpp hive/types.cpp diff --git a/libraries/plugins/peerplays_sidechain/common/utils.cpp b/libraries/plugins/peerplays_sidechain/common/utils.cpp new file mode 100644 index 00000000..c9bdcfc8 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/common/utils.cpp @@ -0,0 +1,15 @@ +#include + +std::string account_id_to_string(graphene::chain::account_id_type account_id) { + std::string account_id_str = fc::to_string(account_id.space_id) + "." + + fc::to_string(account_id.type_id) + "." + + fc::to_string((uint64_t)account_id.instance); + return account_id_str; +} + +std::string asset_id_to_string(graphene::chain::asset_id_type asset_id) { + std::string asset_id_str = fc::to_string(asset_id.space_id) + "." + + fc::to_string(asset_id.type_id) + "." + + fc::to_string((uint64_t)asset_id.instance); + return asset_id_str; +} diff --git a/libraries/plugins/peerplays_sidechain/hive/operations.cpp b/libraries/plugins/peerplays_sidechain/hive/operations.cpp index 3a6ca812..b21b564e 100644 --- a/libraries/plugins/peerplays_sidechain/hive/operations.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/operations.cpp @@ -15,8 +15,8 @@ static std::string trim_typename_namespace(const std::string &name) { } struct from_static_variant_for_hive { - variant &var; - from_static_variant_for_hive(variant &dv) : + fc::variant &var; + from_static_variant_for_hive(fc::variant &dv) : var(dv) { } @@ -24,15 +24,15 @@ struct from_static_variant_for_hive { template void operator()(const T &v) const { auto name = trim_typename_namespace(fc::get_typename::name()); - variant value; + fc::variant value; to_variant(v, value, 5); var = mutable_variant_object("type", name).set("value", value); } }; struct to_static_variant_for_hive { - const variant &var; - to_static_variant_for_hive(const variant &dv) : + const fc::variant &var; + to_static_variant_for_hive(const fc::variant &dv) : var(dv) { } diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp new file mode 100644 index 00000000..4d220d19 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include + +std::string account_id_to_string(graphene::chain::account_id_type account_id); +std::string asset_id_to_string(graphene::chain::asset_id_type asset_id); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 50dfd505..24048cd4 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -55,6 +55,10 @@ protected: std::map private_keys; + std::vector tracked_assets; + bool is_tracked_asset(asset_id_type asset_id); + void on_applied_block(const signed_block &b); + private: }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 6dd19749..e1050158 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -78,8 +78,6 @@ private: 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 diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp index aa094d95..078700f4 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp @@ -23,7 +23,6 @@ public: int64_t settle_sidechain_transaction(const sidechain_transaction_object &sto); private: - void on_applied_block(const signed_block &b); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp index c2d40e14..a35c1933 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp @@ -29,6 +29,8 @@ private: peerplays_sidechain_plugin &plugin; graphene::chain::database &database; std::vector> net_handlers; + + void on_applied_block(const signed_block &b); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index b934c246..ca0e6df7 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -3,12 +3,17 @@ #include #include #include +#include namespace graphene { namespace peerplays_sidechain { sidechain_net_handler::sidechain_net_handler(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : plugin(_plugin), database(_plugin.database()) { + + database.applied_block.connect([&](const signed_block &b) { + on_applied_block(b); + }); } sidechain_net_handler::~sidechain_net_handler() { @@ -570,4 +575,55 @@ void sidechain_net_handler::settle_sidechain_transactions() { }); } +bool sidechain_net_handler::is_tracked_asset(asset_id_type asset_id) { + bool is_tracked_asset = false; + for (const auto &tracked_asset_id : tracked_assets) { + if (asset_id == tracked_asset_id) { + is_tracked_asset = true; + break; + } + } + return is_tracked_asset; +} + +void sidechain_net_handler::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::value) { + transfer_operation transfer_op = op.get(); + if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) { + continue; + } + + if (!is_tracked_asset(transfer_op.amount.asset_id)) { + 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 = account_id_to_string(transfer_op.from); + sed.sidechain_to = account_id_to_string(transfer_op.to); + sed.sidechain_currency = asset_id_to_string(transfer_op.amount.asset_id); + sed.sidechain_amount = transfer_op.amount.amount; + sed.peerplays_from = transfer_op.from; + sed.peerplays_to = transfer_op.to; + price asset_price = database.get(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 diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index adb9182c..9bcd3007 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -910,6 +910,7 @@ void zmq_listener::handle_zmq() { sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::bitcoin; + tracked_assets.push_back(database.get_global_properties().parameters.btc_asset()); ip = options.at("bitcoin-node-ip").as(); zmq_port = options.at("bitcoin-node-zmq-port").as(); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 25b4b3e1..1698ef8b 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -25,8 +25,7 @@ #include #include -namespace graphene { -namespace peerplays_sidechain { +namespace graphene { namespace peerplays_sidechain { hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : rpc_client(_ip, _port, _user, _password) { @@ -120,6 +119,8 @@ std::string hive_wallet_rpc_client::get_account_memo_key(std::string account) { 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; + tracked_assets.push_back(database.get_global_properties().parameters.hbd_asset()); + tracked_assets.push_back(database.get_global_properties().parameters.hive_asset()); node_ip = options.at("hive-node-ip").as(); node_rpc_port = options.at("hive-node-rpc-port").as(); @@ -593,11 +594,14 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { //uint64_t precision = amount_child.get("precision"); std::string nai = amount_child.get("nai"); std::string sidechain_currency = ""; + price sidechain_currency_price = {}; if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) { sidechain_currency = "HBD"; + sidechain_currency_price = database.get(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate; } if ((nai == "@@000000021") /*?? HIVE*/ || (nai == "@@000000021" /*TESTS*/)) { sidechain_currency = "HIVE"; + sidechain_currency_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; } if (to == "son-account") { @@ -623,8 +627,7 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { sed.sidechain_amount = amount; sed.peerplays_from = addr_itr->sidechain_address_account; sed.peerplays_to = database.get_global_properties().parameters.son_account(); - price hive_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; - sed.peerplays_asset = asset(sed.sidechain_amount * hive_price.base.amount / hive_price.quote.amount); + sed.peerplays_asset = asset(sed.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount); sidechain_event_data_received(sed); } } @@ -634,40 +637,4 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { } } -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::value) { - // transfer_operation transfer_op = op.get(); - // 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(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 +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 5e481410..641d9abf 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -25,6 +25,15 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::peerplays; + const auto &assets_by_symbol = database.get_index_type().indices().get(); + const auto get_asset_id = [&assets_by_symbol](const string &symbol) { + auto asset_itr = assets_by_symbol.find(symbol); + FC_ASSERT(asset_itr != assets_by_symbol.end(), "Unable to find asset '${sym}'", ("sym", symbol)); + return asset_itr->get_id(); + }; + //tracked_assets.push_back(get_asset_id("PBTC")); + //tracked_assets.push_back(get_asset_id("PETH")); + //tracked_assets.push_back(get_asset_id("PEOS")); if (options.count("peerplays-private-key")) { const std::vector pub_priv_keys = options["peerplays-private-key"].as>(); @@ -37,10 +46,6 @@ sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidec private_keys[key_pair.first] = key_pair.second; } } - - database.applied_block.connect([&](const signed_block &b) { - on_applied_block(b); - }); } sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() { @@ -271,40 +276,4 @@ int64_t sidechain_net_handler_peerplays::settle_sidechain_transaction(const side return settle_amount; } -void sidechain_net_handler_peerplays::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::value) { - transfer_operation transfer_op = op.get(); - 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(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 diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 4fa792b4..33f869b1 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -11,6 +11,10 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_manager::sidechain_net_manager(peerplays_sidechain_plugin &_plugin) : plugin(_plugin), database(_plugin.database()) { + + database.applied_block.connect([&](const signed_block &b) { + on_applied_block(b); + }); } sidechain_net_manager::~sidechain_net_manager() { @@ -94,4 +98,7 @@ void sidechain_net_manager::settle_sidechain_transactions() { } } +void sidechain_net_manager::on_applied_block(const signed_block &b) { +} + }} // namespace graphene::peerplays_sidechain -- 2.45.2 From 09f23dade8431f2deee919669e7f6a1716e3cd03 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 26 Apr 2021 13:05:27 +0200 Subject: [PATCH 15/57] Withdrawal object creation --- .../peerplays_sidechain/CMakeLists.txt | 1 + .../peerplays_sidechain/hive/asset.cpp | 263 +++++++++++++++ .../peerplays_sidechain/hive/asset_symbol.cpp | 300 ++++++++++++++++++ .../peerplays_sidechain/hive/transaction.cpp | 10 +- .../peerplays_sidechain/hive/asset.hpp | 20 ++ .../peerplays_sidechain/hive/asset_symbol.hpp | 245 ++++++++++++++ .../hive/hive_operations.hpp | 11 +- .../peerplays_sidechain/hive/types.hpp | 2 +- .../peerplays_sidechain/hive/types_fwd.hpp | 90 ++++++ .../sidechain_net_handler.cpp | 53 +++- .../sidechain_net_handler_hive.cpp | 108 +++++++ 11 files changed, 1085 insertions(+), 18 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/hive/asset.cpp create mode 100644 libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 60eb03c8..48dd44f1 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -16,6 +16,7 @@ add_library( peerplays_sidechain bitcoin/sign_bitcoin_transaction.cpp common/rpc_client.cpp common/utils.cpp + hive/asset.cpp hive/operations.cpp hive/transaction.cpp hive/types.cpp diff --git a/libraries/plugins/peerplays_sidechain/hive/asset.cpp b/libraries/plugins/peerplays_sidechain/hive/asset.cpp new file mode 100644 index 00000000..e27c0494 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/asset.cpp @@ -0,0 +1,263 @@ +#include + +#include + +#include +#include + +#define ASSET_AMOUNT_KEY "amount" +#define ASSET_PRECISION_KEY "precision" +#define ASSET_NAI_KEY "nai" + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +std::string asset_symbol_type::to_string() const { + return fc::json::to_string(fc::variant(*this, 5)); +} + +asset_symbol_type asset_symbol_type::from_string(const std::string &str) { + return fc::json::from_string(str).as(5); +} + +void asset_symbol_type::to_nai_string(char *buf) const { + static_assert(HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH >= 12, "This code will overflow a short buffer"); + uint32_t x = to_nai(); + buf[11] = '\0'; + buf[10] = ((x % 10) + '0'); + x /= 10; + buf[9] = ((x % 10) + '0'); + x /= 10; + buf[8] = ((x % 10) + '0'); + x /= 10; + buf[7] = ((x % 10) + '0'); + x /= 10; + buf[6] = ((x % 10) + '0'); + x /= 10; + buf[5] = ((x % 10) + '0'); + x /= 10; + buf[4] = ((x % 10) + '0'); + x /= 10; + buf[3] = ((x % 10) + '0'); + x /= 10; + buf[2] = ((x) + '0'); + buf[1] = '@'; + buf[0] = '@'; +} + +asset_symbol_type asset_symbol_type::from_nai_string(const char *p, uint8_t decimal_places) { + try { + FC_ASSERT(p != nullptr, "NAI string cannot be a null"); + FC_ASSERT(std::strlen(p) == HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - 1, "Incorrect NAI string length"); + FC_ASSERT(p[0] == '@' && p[1] == '@', "Invalid NAI string prefix"); + uint32_t nai = boost::lexical_cast(p + 2); + return asset_symbol_type::from_nai(nai, decimal_places); + } + FC_CAPTURE_AND_RETHROW(); +} + +// Highly optimized implementation of Damm algorithm +// https://en.wikipedia.org/wiki/Damm_algorithm +uint8_t asset_symbol_type::damm_checksum_8digit(uint32_t value) { + FC_ASSERT(value < 100000000); + + const uint8_t t[] = { + 0, 30, 10, 70, 50, 90, 80, 60, 40, 20, + 70, 0, 90, 20, 10, 50, 40, 80, 60, 30, + 40, 20, 0, 60, 80, 70, 10, 30, 50, 90, + 10, 70, 50, 0, 90, 80, 30, 40, 20, 60, + 60, 10, 20, 30, 0, 40, 50, 90, 70, 80, + 30, 60, 70, 40, 20, 0, 90, 50, 80, 10, + 50, 80, 60, 90, 70, 20, 0, 10, 30, 40, + 80, 90, 40, 50, 30, 60, 20, 0, 10, 70, + 90, 40, 30, 80, 60, 10, 70, 20, 0, 50, + 20, 50, 80, 10, 40, 30, 60, 70, 90, 0}; + + uint32_t q0 = value / 10; + uint32_t d0 = value % 10; + uint32_t q1 = q0 / 10; + uint32_t d1 = q0 % 10; + uint32_t q2 = q1 / 10; + uint32_t d2 = q1 % 10; + uint32_t q3 = q2 / 10; + uint32_t d3 = q2 % 10; + uint32_t q4 = q3 / 10; + uint32_t d4 = q3 % 10; + uint32_t q5 = q4 / 10; + uint32_t d5 = q4 % 10; + uint32_t d6 = q5 % 10; + uint32_t d7 = q5 / 10; + + uint8_t x = t[d7]; + x = t[x + d6]; + x = t[x + d5]; + x = t[x + d4]; + x = t[x + d3]; + x = t[x + d2]; + x = t[x + d1]; + x = t[x + d0]; + return x / 10; +} + +uint32_t asset_symbol_type::asset_num_from_nai(uint32_t nai, uint8_t decimal_places) { + // Can be replaced with some clever bitshifting + uint32_t nai_check_digit = nai % 10; + uint32_t nai_data_digits = nai / 10; + + FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & (nai_data_digits <= SMT_MAX_NAI), "NAI out of range"); + FC_ASSERT(nai_check_digit == damm_checksum_8digit(nai_data_digits), "Invalid check digit"); + + switch (nai_data_digits) { + case HIVE_NAI_HIVE: + FC_ASSERT(decimal_places == HIVE_PRECISION_HIVE); + return HIVE_ASSET_NUM_HIVE; + case HIVE_NAI_HBD: + FC_ASSERT(decimal_places == HIVE_PRECISION_HBD); + return HIVE_ASSET_NUM_HBD; + case HIVE_NAI_VESTS: + FC_ASSERT(decimal_places == HIVE_PRECISION_VESTS); + return HIVE_ASSET_NUM_VESTS; + default: + FC_ASSERT(decimal_places <= HIVE_ASSET_MAX_DECIMALS, "Invalid decimal_places"); + return (nai_data_digits << HIVE_NAI_SHIFT) | SMT_ASSET_NUM_CONTROL_MASK | decimal_places; + } +} + +uint32_t asset_symbol_type::to_nai() const { + uint32_t nai_data_digits = 0; + + // Can be replaced with some clever bitshifting + switch (asset_num) { + case HIVE_ASSET_NUM_HIVE: + nai_data_digits = HIVE_NAI_HIVE; + break; + case HIVE_ASSET_NUM_HBD: + nai_data_digits = HIVE_NAI_HBD; + break; + case HIVE_ASSET_NUM_VESTS: + nai_data_digits = HIVE_NAI_VESTS; + break; + default: + FC_ASSERT(space() == smt_nai_space); + nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); + } + + uint32_t nai_check_digit = damm_checksum_8digit(nai_data_digits); + return nai_data_digits * 10 + nai_check_digit; +} + +bool asset_symbol_type::is_vesting() const { + switch (space()) { + case legacy_space: { + switch (asset_num) { + case HIVE_ASSET_NUM_HIVE: + return false; + case HIVE_ASSET_NUM_HBD: + // HBD is certainly liquid. + return false; + case HIVE_ASSET_NUM_VESTS: + return true; + default: + FC_ASSERT(false, "Unknown asset symbol"); + } + } + case smt_nai_space: + // 6th bit of asset_num is used as vesting/liquid variant indicator. + return asset_num & SMT_ASSET_NUM_VESTING_MASK; + default: + FC_ASSERT(false, "Unknown asset symbol"); + } +} + +asset_symbol_type asset_symbol_type::get_paired_symbol() const { + switch (space()) { + case legacy_space: { + switch (asset_num) { + case HIVE_ASSET_NUM_HIVE: + return from_asset_num(HIVE_ASSET_NUM_VESTS); + case HIVE_ASSET_NUM_HBD: + return *this; + case HIVE_ASSET_NUM_VESTS: + return from_asset_num(HIVE_ASSET_NUM_HIVE); + default: + FC_ASSERT(false, "Unknown asset symbol"); + } + } + case smt_nai_space: { + // Toggle 6th bit of this asset_num. + auto paired_asset_num = asset_num ^ (SMT_ASSET_NUM_VESTING_MASK); + return from_asset_num(paired_asset_num); + } + default: + FC_ASSERT(false, "Unknown asset symbol"); + } +} + +asset_symbol_type::asset_symbol_space asset_symbol_type::space() const { + asset_symbol_type::asset_symbol_space s = legacy_space; + switch (asset_num) { + case HIVE_ASSET_NUM_HIVE: + case HIVE_ASSET_NUM_HBD: + case HIVE_ASSET_NUM_VESTS: + s = legacy_space; + break; + default: + s = smt_nai_space; + } + return s; +} + +void asset_symbol_type::validate() const { + switch (asset_num) { + case HIVE_ASSET_NUM_HIVE: + case HIVE_ASSET_NUM_HBD: + case HIVE_ASSET_NUM_VESTS: + break; + default: { + uint32_t nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); + uint32_t nai_1bit = (asset_num & SMT_ASSET_NUM_CONTROL_MASK); + uint32_t nai_decimal_places = (asset_num & SMT_ASSET_NUM_PRECISION_MASK); + FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & + (nai_data_digits <= SMT_MAX_NAI) & + (nai_1bit == SMT_ASSET_NUM_CONTROL_MASK) & + (nai_decimal_places <= HIVE_ASSET_MAX_DECIMALS), + "Cannot determine space for asset ${n}", ("n", asset_num)); + } + } + // this assert is duplicated by above code in all cases + // FC_ASSERT( decimals() <= HIVE_ASSET_MAX_DECIMALS ); +} + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth) { + try { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(var.symbol.decimals()))(ASSET_NAI_KEY, var.symbol.to_nai_string()); + vo = v; + } + FC_CAPTURE_AND_RETHROW() +} + +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset &vo, uint32_t max_depth) { + try { + FC_ASSERT(var.is_object(), "Asset has to be treated as object."); + + const auto &v_object = var.get_object(); + + FC_ASSERT(v_object.contains(ASSET_AMOUNT_KEY), "Amount field doesn't exist."); + FC_ASSERT(v_object[ASSET_AMOUNT_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_AMOUNT_KEY)); + vo.amount = boost::lexical_cast(v_object[ASSET_AMOUNT_KEY].as(max_depth)); + FC_ASSERT(vo.amount >= 0, "Asset amount cannot be negative"); + + FC_ASSERT(v_object.contains(ASSET_PRECISION_KEY), "Precision field doesn't exist."); + FC_ASSERT(v_object[ASSET_PRECISION_KEY].is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_PRECISION_KEY)); + + FC_ASSERT(v_object.contains(ASSET_NAI_KEY), "NAI field doesn't exist."); + FC_ASSERT(v_object[ASSET_NAI_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_NAI_KEY)); + + vo.symbol = graphene::peerplays_sidechain::hive::asset_symbol_type::from_nai_string(v_object[ASSET_NAI_KEY].as(max_depth).c_str(), v_object[ASSET_PRECISION_KEY].as(max_depth)); + } + FC_CAPTURE_AND_RETHROW() +} +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp b/libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp new file mode 100644 index 00000000..a44b9138 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp @@ -0,0 +1,300 @@ +//#include +// +//#include +// +//namespace graphene { namespace peerplays_sidechain { namespace hive { +// +//std::string asset_symbol_type::to_string() const { +// return fc::json::to_string(fc::variant(*this, 5)); +//} +// +//asset_symbol_type asset_symbol_type::from_string(const std::string &str) { +// return fc::json::from_string(str).as(5); +//} +// +//void asset_symbol_type::to_nai_string(char *buf) const { +// static_assert(HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH >= 12, "This code will overflow a short buffer"); +// uint32_t x = to_nai(); +// buf[11] = '\0'; +// buf[10] = ((x % 10) + '0'); +// x /= 10; +// buf[9] = ((x % 10) + '0'); +// x /= 10; +// buf[8] = ((x % 10) + '0'); +// x /= 10; +// buf[7] = ((x % 10) + '0'); +// x /= 10; +// buf[6] = ((x % 10) + '0'); +// x /= 10; +// buf[5] = ((x % 10) + '0'); +// x /= 10; +// buf[4] = ((x % 10) + '0'); +// x /= 10; +// buf[3] = ((x % 10) + '0'); +// x /= 10; +// buf[2] = ((x) + '0'); +// buf[1] = '@'; +// buf[0] = '@'; +//} +// +//asset_symbol_type asset_symbol_type::from_nai_string(const char *p, uint8_t decimal_places) { +// try { +// FC_ASSERT(p != nullptr, "NAI string cannot be a null"); +// FC_ASSERT(std::strlen(p) == HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - 1, "Incorrect NAI string length"); +// FC_ASSERT(p[0] == '@' && p[1] == '@', "Invalid NAI string prefix"); +// uint32_t nai = boost::lexical_cast(p + 2); +// return asset_symbol_type::from_nai(nai, decimal_places); +// } +// FC_CAPTURE_AND_RETHROW(); +//} +// +//// Highly optimized implementation of Damm algorithm +//// https://en.wikipedia.org/wiki/Damm_algorithm +//uint8_t asset_symbol_type::damm_checksum_8digit(uint32_t value) { +// FC_ASSERT(value < 100000000); +// +// const uint8_t t[] = { +// 0, 30, 10, 70, 50, 90, 80, 60, 40, 20, +// 70, 0, 90, 20, 10, 50, 40, 80, 60, 30, +// 40, 20, 0, 60, 80, 70, 10, 30, 50, 90, +// 10, 70, 50, 0, 90, 80, 30, 40, 20, 60, +// 60, 10, 20, 30, 0, 40, 50, 90, 70, 80, +// 30, 60, 70, 40, 20, 0, 90, 50, 80, 10, +// 50, 80, 60, 90, 70, 20, 0, 10, 30, 40, +// 80, 90, 40, 50, 30, 60, 20, 0, 10, 70, +// 90, 40, 30, 80, 60, 10, 70, 20, 0, 50, +// 20, 50, 80, 10, 40, 30, 60, 70, 90, 0}; +// +// uint32_t q0 = value / 10; +// uint32_t d0 = value % 10; +// uint32_t q1 = q0 / 10; +// uint32_t d1 = q0 % 10; +// uint32_t q2 = q1 / 10; +// uint32_t d2 = q1 % 10; +// uint32_t q3 = q2 / 10; +// uint32_t d3 = q2 % 10; +// uint32_t q4 = q3 / 10; +// uint32_t d4 = q3 % 10; +// uint32_t q5 = q4 / 10; +// uint32_t d5 = q4 % 10; +// uint32_t d6 = q5 % 10; +// uint32_t d7 = q5 / 10; +// +// uint8_t x = t[d7]; +// x = t[x + d6]; +// x = t[x + d5]; +// x = t[x + d4]; +// x = t[x + d3]; +// x = t[x + d2]; +// x = t[x + d1]; +// x = t[x + d0]; +// return x / 10; +//} +// +//uint32_t asset_symbol_type::asset_num_from_nai(uint32_t nai, uint8_t decimal_places) { +// // Can be replaced with some clever bitshifting +// uint32_t nai_check_digit = nai % 10; +// uint32_t nai_data_digits = nai / 10; +// +// FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & (nai_data_digits <= SMT_MAX_NAI), "NAI out of range"); +// FC_ASSERT(nai_check_digit == damm_checksum_8digit(nai_data_digits), "Invalid check digit"); +// +// switch (nai_data_digits) { +// case HIVE_NAI_HIVE: +// FC_ASSERT(decimal_places == HIVE_PRECISION_HIVE); +// return HIVE_ASSET_NUM_HIVE; +// case HIVE_NAI_HBD: +// FC_ASSERT(decimal_places == HIVE_PRECISION_HBD); +// return HIVE_ASSET_NUM_HBD; +// case HIVE_NAI_VESTS: +// FC_ASSERT(decimal_places == HIVE_PRECISION_VESTS); +// return HIVE_ASSET_NUM_VESTS; +// default: +// FC_ASSERT(decimal_places <= HIVE_ASSET_MAX_DECIMALS, "Invalid decimal_places"); +// return (nai_data_digits << HIVE_NAI_SHIFT) | SMT_ASSET_NUM_CONTROL_MASK | decimal_places; +// } +//} +// +//uint32_t asset_symbol_type::to_nai() const { +// uint32_t nai_data_digits = 0; +// +// // Can be replaced with some clever bitshifting +// switch (asset_num) { +// case HIVE_ASSET_NUM_HIVE: +// nai_data_digits = HIVE_NAI_HIVE; +// break; +// case HIVE_ASSET_NUM_HBD: +// nai_data_digits = HIVE_NAI_HBD; +// break; +// case HIVE_ASSET_NUM_VESTS: +// nai_data_digits = HIVE_NAI_VESTS; +// break; +// default: +// FC_ASSERT(space() == smt_nai_space); +// nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); +// } +// +// uint32_t nai_check_digit = damm_checksum_8digit(nai_data_digits); +// return nai_data_digits * 10 + nai_check_digit; +//} +// +//bool asset_symbol_type::is_vesting() const { +// switch (space()) { +// case legacy_space: { +// switch (asset_num) { +// case HIVE_ASSET_NUM_HIVE: +// return false; +// case HIVE_ASSET_NUM_HBD: +// // HBD is certainly liquid. +// return false; +// case HIVE_ASSET_NUM_VESTS: +// return true; +// default: +// FC_ASSERT(false, "Unknown asset symbol"); +// } +// } +// case smt_nai_space: +// // 6th bit of asset_num is used as vesting/liquid variant indicator. +// return asset_num & SMT_ASSET_NUM_VESTING_MASK; +// default: +// FC_ASSERT(false, "Unknown asset symbol"); +// } +//} +// +//asset_symbol_type asset_symbol_type::get_paired_symbol() const { +// switch (space()) { +// case legacy_space: { +// switch (asset_num) { +// case HIVE_ASSET_NUM_HIVE: +// return from_asset_num(HIVE_ASSET_NUM_VESTS); +// case HIVE_ASSET_NUM_HBD: +// return *this; +// case HIVE_ASSET_NUM_VESTS: +// return from_asset_num(HIVE_ASSET_NUM_HIVE); +// default: +// FC_ASSERT(false, "Unknown asset symbol"); +// } +// } +// case smt_nai_space: { +// // Toggle 6th bit of this asset_num. +// auto paired_asset_num = asset_num ^ (SMT_ASSET_NUM_VESTING_MASK); +// return from_asset_num(paired_asset_num); +// } +// default: +// FC_ASSERT(false, "Unknown asset symbol"); +// } +//} +// +//asset_symbol_type::asset_symbol_space asset_symbol_type::space() const { +// asset_symbol_type::asset_symbol_space s = legacy_space; +// switch (asset_num) { +// case HIVE_ASSET_NUM_HIVE: +// case HIVE_ASSET_NUM_HBD: +// case HIVE_ASSET_NUM_VESTS: +// s = legacy_space; +// break; +// default: +// s = smt_nai_space; +// } +// return s; +//} +// +//void asset_symbol_type::validate() const { +// switch (asset_num) { +// case HIVE_ASSET_NUM_HIVE: +// case HIVE_ASSET_NUM_HBD: +// case HIVE_ASSET_NUM_VESTS: +// break; +// default: { +// uint32_t nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); +// uint32_t nai_1bit = (asset_num & SMT_ASSET_NUM_CONTROL_MASK); +// uint32_t nai_decimal_places = (asset_num & SMT_ASSET_NUM_PRECISION_MASK); +// FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & +// (nai_data_digits <= SMT_MAX_NAI) & +// (nai_1bit == SMT_ASSET_NUM_CONTROL_MASK) & +// (nai_decimal_places <= HIVE_ASSET_MAX_DECIMALS), +// "Cannot determine space for asset ${n}", ("n", asset_num)); +// } +// } +// // this assert is duplicated by above code in all cases +// // FC_ASSERT( decimals() <= HIVE_ASSET_MAX_DECIMALS ); +//} +// +//}}} // namespace graphene::peerplays_sidechain::hive +// +//namespace fc { +// +//namespace raw { +// +//// Legacy serialization of assets +//// 0000pppp aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff 00000000 +//// Symbol = abcdef +//// +//// NAI serialization of assets +//// aaa1pppp bbbbbbbb cccccccc dddddddd +//// NAI = (MSB to LSB) dddddddd cccccccc bbbbbbbb aaa +//// +//// NAI internal storage of legacy assets +// +////template +////void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t, uint32_t max_depth) { +//// uint64_t ser = 0; +//// s.read((char *)&ser, 4); +//// +//// switch (ser) { +//// case OBSOLETE_SYMBOL_SER & 0xFFFFFFFF: +//// s.read(((char *)&ser) + 4, 4); +//// FC_ASSERT(ser == OBSOLETE_SYMBOL_SER, "invalid asset bits"); +//// sym.asset_num = HIVE_ASSET_NUM_HIVE; +//// break; +//// case OBD_SYMBOL_SER & 0xFFFFFFFF: +//// s.read(((char *)&ser) + 4, 4); +//// FC_ASSERT(ser == OBD_SYMBOL_SER, "invalid asset bits"); +//// sym.asset_num = HIVE_ASSET_NUM_HBD; +//// break; +//// case VESTS_SYMBOL_SER & 0xFFFFFFFF: +//// s.read(((char *)&ser) + 4, 4); +//// FC_ASSERT(ser == VESTS_SYMBOL_SER, "invalid asset bits"); +//// sym.asset_num = HIVE_ASSET_NUM_VESTS; +//// break; +//// default: +//// sym.asset_num = uint32_t(ser); +//// } +//// sym.validate(); +////} +// +//} // namespace raw +//// +////void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &var, uint32_t max_depth) { +//// try { +//// mutable_variant_object o; +//// o(ASSET_SYMBOL_NAI_KEY, sym.to_nai_string())(ASSET_SYMBOL_DECIMALS_KEY, sym.decimals()); +//// var = std::move(o); +//// } +//// FC_CAPTURE_AND_RETHROW() +////} +//// +////void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t max_depth) { +//// using graphene::peerplays_sidechain::hive::asset_symbol_type; +//// +//// try { +//// FC_ASSERT(var.is_object(), "Asset symbol is expected to be an object."); +//// +//// auto &o = var.get_object(); +//// +//// auto nai = o.find(ASSET_SYMBOL_NAI_KEY); +//// FC_ASSERT(nai != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); +//// FC_ASSERT(nai->value().is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); +//// +//// auto decimals = o.find(ASSET_SYMBOL_DECIMALS_KEY); +//// FC_ASSERT(decimals != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); +//// FC_ASSERT(decimals->value().is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); +//// FC_ASSERT(decimals->value().as_uint64() <= HIVE_ASSET_MAX_DECIMALS, +//// "Expected decimals to be less than or equal to ${num}", ("num", HIVE_ASSET_MAX_DECIMALS)); +//// +//// sym = asset_symbol_type::from_nai_string(nai->value().as_string().c_str(), decimals->value().as(max_depth)); +//// } +//// FC_CAPTURE_AND_RETHROW() +////} +// +//} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp index a5c8bcfd..0e0ff8ed 100644 --- a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp @@ -67,7 +67,15 @@ signature_type signed_transaction::sign(const hive::private_key_type &key, const digest_type::encoder enc; fc::raw::pack(enc, chain_id); fc::raw::pack(enc, *this); - return key.sign_compact(enc.result(), true); + auto sig = key.sign_compact(enc.result(), true); + + ilog("Signing2: chain_id = ${chain_id}", ("chain_id", chain_id)); + ilog("Signing2: key = ${key}", ("key", key)); + ilog("Signing2: this = ${this}", ("this", *this)); + ilog("Signing2: h = ${h}", ("h", enc.result())); + ilog("Signing2: signature = ${sig}", ("sig", sig)); + + return sig; } }}} // namespace graphene::peerplays_sidechain::hive diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp new file mode 100644 index 00000000..aaab642f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct asset { + share_type amount; + asset_symbol_type symbol; +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { +void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth); +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset &vo, uint32_t max_depth); +} // namespace fc + +FC_REFLECT(graphene::peerplays_sidechain::hive::asset, (amount)(symbol)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp new file mode 100644 index 00000000..4eb1d9b0 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp @@ -0,0 +1,245 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define HIVE_ASSET_SYMBOL_PRECISION_BITS 4 +#define HIVE_ASSET_CONTROL_BITS 1 +#define HIVE_NAI_SHIFT (HIVE_ASSET_SYMBOL_PRECISION_BITS + HIVE_ASSET_CONTROL_BITS) +#define SMT_MAX_NAI 99999999 +#define SMT_MIN_NAI 1 +#define SMT_MIN_NON_RESERVED_NAI 10000000 +#define HIVE_ASSET_SYMBOL_NAI_LENGTH 10 +#define HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH (HIVE_ASSET_SYMBOL_NAI_LENGTH + 2) +#define SMT_MAX_NAI_POOL_COUNT 10 +#define SMT_MAX_NAI_GENERATION_TRIES 100 + +#define HIVE_PRECISION_HBD (3) +#define HIVE_PRECISION_HIVE (3) +#define HIVE_PRECISION_VESTS (6) + +// One's place is used for check digit, which means NAI 0-9 all have NAI data of 0 which is invalid +// This space is safe to use because it would alwasys result in failure to convert from NAI +#define HIVE_NAI_HBD (1) +#define HIVE_NAI_HIVE (2) +#define HIVE_NAI_VESTS (3) + +#define HIVE_ASSET_NUM_HBD (uint32_t(((SMT_MAX_NAI + HIVE_NAI_HBD) << HIVE_NAI_SHIFT) | HIVE_PRECISION_HBD)) +#define HIVE_ASSET_NUM_HIVE (uint32_t(((SMT_MAX_NAI + HIVE_NAI_HIVE) << HIVE_NAI_SHIFT) | HIVE_PRECISION_HIVE)) +#define HIVE_ASSET_NUM_VESTS (uint32_t(((SMT_MAX_NAI + HIVE_NAI_VESTS) << HIVE_NAI_SHIFT) | HIVE_PRECISION_VESTS)) + +#ifdef IS_TEST_NET + +#define VESTS_SYMBOL_U64 (uint64_t('V') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32)) +my #define HIVE_SYMBOL_U64 OBSOLETE_SYMBOL_U64 +#define OBD_SYMBOL_U64 (uint64_t('T') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define HBD_SYMBOL_U64 OBD_SYMBOL_U64 +#else + +#define VESTS_SYMBOL_U64 (uint64_t('V') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32)) +#define OBSOLETE_SYMBOL_U64 (uint64_t('S') | (uint64_t('T') << 8) | (uint64_t('E') << 16) | (uint64_t('E') << 24) | (uint64_t('M') << 32)) +#define HIVE_SYMBOL_U64 (uint64_t('H') | (uint64_t('I') << 8) | (uint64_t('V') << 16) | (uint64_t('E') << 24)) +#define OBD_SYMBOL_U64 (uint64_t('S') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define HBD_SYMBOL_U64 (uint64_t('H') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) + +#endif + +#define VESTS_SYMBOL_SER (uint64_t(6) | (VESTS_SYMBOL_U64 << 8)) ///< VESTS|VESTS with 6 digits of precision +#define OBSOLETE_SYMBOL_SER (uint64_t(3) | (OBSOLETE_SYMBOL_U64 << 8)) ///< STEEM|TESTS with 3 digits of precision +#define OBD_SYMBOL_SER (uint64_t(3) | (OBD_SYMBOL_U64 << 8)) ///< SBD|TBD with 3 digits of precision + +#define HIVE_ASSET_MAX_DECIMALS 12 + +#define SMT_ASSET_NUM_PRECISION_MASK 0xF +#define SMT_ASSET_NUM_CONTROL_MASK 0x10 +#define SMT_ASSET_NUM_VESTING_MASK 0x20 + +#define ASSET_SYMBOL_NAI_KEY "nai" +#define ASSET_SYMBOL_DECIMALS_KEY "decimals" + + namespace graphene { + namespace peerplays_sidechain { namespace hive { + + class asset_symbol_type { + public: + enum asset_symbol_space { + legacy_space = 1, + smt_nai_space = 2 + }; + + explicit operator uint32_t() { + return to_nai(); + } + + static asset_symbol_type from_string(const std::string &str); + // buf must have space for HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH + static asset_symbol_type from_nai_string(const char *buf, uint8_t decimal_places); + static asset_symbol_type from_asset_num(uint32_t asset_num) { + asset_symbol_type result; + result.asset_num = asset_num; + return result; + } + static uint32_t asset_num_from_nai(uint32_t nai, uint8_t decimal_places); + static asset_symbol_type from_nai(uint32_t nai, uint8_t decimal_places) { + return from_asset_num(asset_num_from_nai(nai, decimal_places)); + } + static uint8_t damm_checksum_8digit(uint32_t value); + + std::string to_string() const; + + void to_nai_string(char *buf) const; + std::string to_nai_string() const { + char buf[HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH]; + to_nai_string(buf); + return std::string(buf); + } + + uint32_t to_nai() const; + + /**Returns true when symbol represents vesting variant of the token, + * false for liquid one. + */ + bool is_vesting() const; + /**Returns vesting symbol when called from liquid one + * and liquid symbol when called from vesting one. + * Returns back the HBD symbol if represents HBD. + */ + asset_symbol_type get_paired_symbol() const; + /**Returns asset_num stripped of precision holding bits. + * \warning checking that it's SMT symbol is caller responsibility. + */ + uint32_t get_stripped_precision_smt_num() const { + return asset_num & ~(SMT_ASSET_NUM_PRECISION_MASK); + } + + asset_symbol_space space() const; + uint8_t decimals() const { + return uint8_t(asset_num & SMT_ASSET_NUM_PRECISION_MASK); + } + + void validate() const; + + uint32_t asset_num = 0; + uint64_t ser = OBSOLETE_SYMBOL_SER; + }; + + }} // namespace peerplays_sidechain::hive +} // namespace graphene + +FC_REFLECT(graphene::peerplays_sidechain::hive::asset_symbol_type, (asset_num)) + +namespace fc { + +namespace raw { + +// Legacy serialization of assets +// 0000pppp aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff 00000000 +// Symbol = abcdef +// +// NAI serialization of assets +// aaa1pppp bbbbbbbb cccccccc dddddddd +// NAI = (MSB to LSB) dddddddd cccccccc bbbbbbbb aaa +// +// NAI internal storage of legacy assets + +template +void pack(Stream &s, const graphene::peerplays_sidechain::hive::asset_symbol_type &sym) { + std::cout << "##### PACK ###" << std::endl; + switch (sym.space()) { + case graphene::peerplays_sidechain::hive::asset_symbol_type::legacy_space: { + uint64_t ser = 0; + switch (sym.asset_num) { + case HIVE_ASSET_NUM_HIVE: + ser = OBSOLETE_SYMBOL_SER; + break; + case HIVE_ASSET_NUM_HBD: + ser = OBD_SYMBOL_SER; + break; + case HIVE_ASSET_NUM_VESTS: + ser = VESTS_SYMBOL_SER; + break; + default: + FC_ASSERT(false, "Cannot serialize unknown asset symbol"); + } + pack(s, ser); + break; + } + case graphene::peerplays_sidechain::hive::asset_symbol_type::smt_nai_space: + pack(s, sym.asset_num); + break; + default: + FC_ASSERT(false, "Cannot serialize unknown asset symbol"); + } +} + +template +void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym) { + std::cout << "##### UNPACK ###" << std::endl; + uint64_t ser = 0; + s.read((char *)&ser, 4); + + switch (ser) { + case OBSOLETE_SYMBOL_SER & 0xFFFFFFFF: + s.read(((char *)&ser) + 4, 4); + FC_ASSERT(ser == OBSOLETE_SYMBOL_SER, "invalid asset bits"); + sym.asset_num = HIVE_ASSET_NUM_HIVE; + break; + case OBD_SYMBOL_SER & 0xFFFFFFFF: + s.read(((char *)&ser) + 4, 4); + FC_ASSERT(ser == OBD_SYMBOL_SER, "invalid asset bits"); + sym.asset_num = HIVE_ASSET_NUM_HBD; + break; + case VESTS_SYMBOL_SER & 0xFFFFFFFF: + s.read(((char *)&ser) + 4, 4); + FC_ASSERT(ser == VESTS_SYMBOL_SER, "invalid asset bits"); + sym.asset_num = HIVE_ASSET_NUM_VESTS; + break; + default: + sym.asset_num = uint32_t(ser); + } + sym.validate(); +} + +} // namespace raw + +inline void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &var, uint32_t max_depth) { + try { + mutable_variant_object o; + o(ASSET_SYMBOL_NAI_KEY, sym.to_nai_string())(ASSET_SYMBOL_DECIMALS_KEY, sym.decimals()); + var = std::move(o); + } + FC_CAPTURE_AND_RETHROW() +} + +inline void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t max_depth) { + using graphene::peerplays_sidechain::hive::asset_symbol_type; + + try { + FC_ASSERT(var.is_object(), "Asset symbol is expected to be an object."); + + auto &o = var.get_object(); + + auto nai = o.find(ASSET_SYMBOL_NAI_KEY); + FC_ASSERT(nai != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); + FC_ASSERT(nai->value().is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); + + auto decimals = o.find(ASSET_SYMBOL_DECIMALS_KEY); + FC_ASSERT(decimals != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); + FC_ASSERT(decimals->value().is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); + FC_ASSERT(decimals->value().as_uint64() <= HIVE_ASSET_MAX_DECIMALS, + "Expected decimals to be less than or equal to ${num}", ("num", HIVE_ASSET_MAX_DECIMALS)); + + sym = asset_symbol_type::from_nai_string(nai->value().as_string().c_str(), decimals->value().as(max_depth)); + } + FC_CAPTURE_AND_RETHROW() +} + +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp index cac3b03f..e19060f8 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -15,7 +16,12 @@ struct vote_operation {}; struct comment_operation {}; -struct transfer_operation {}; +struct transfer_operation { + hive::account_name_type from; + hive::account_name_type to; + hive::asset amount; + std::string memo; +}; struct transfer_to_vesting_operation {}; @@ -44,7 +50,8 @@ struct account_update_operation { FC_REFLECT(graphene::peerplays_sidechain::hive::vote_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::comment_operation, ) -FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_operation, + (from)(to)(amount)(memo)) FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_vesting_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::withdraw_vesting_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create_operation, ) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp index e49556d3..724373e5 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -18,7 +18,7 @@ typedef fc::ripemd160 block_id_type; typedef fc::ripemd160 transaction_id_type; typedef fc::sha256 digest_type; typedef fc::ecc::compact_signature signature_type; -//typedef safe share_type; +typedef fc::safe share_type; //typedef safe ushare_type; //typedef uint16_t weight_type; //typedef uint32_t contribution_id_type; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp new file mode 100644 index 00000000..7276f297 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp @@ -0,0 +1,90 @@ +//#pragma once +//#include +//#include +//#include +// +//#include "asset_symbol.hpp" +// +//namespace fc { +//class variant; +//} // namespace fc +// +//namespace graphene { namespace peerplays_sidechain { namespace hive { +////template< typename Storage = fc::uint128 > +////class fixed_string_impl; +// +//class asset_symbol_type; +////class legacy_hive_asset_symbol_type; +////struct legacy_hive_asset; +//}}} // namespace graphene::peerplays_sidechain::hive +// +////using boost::container::flat_set; +//// +////template< class Key > +////class flat_set_ex: public flat_set< Key > +////{ +//// public: +//// +//// flat_set_ex& operator=( const flat_set< Key >& obj ) +//// { +//// flat_set< Key >::operator=( obj ); +//// return *this; +//// } +//// +//// flat_set_ex& operator=( const flat_set_ex& obj ) +//// { +//// flat_set< Key >::operator=( obj ); +//// return *this; +//// } +////}; +// +//namespace fc { +//namespace raw { +// +////template +////void pack( Stream& s, const flat_set_ex& value ); +////template +////void unpack( Stream& s, flat_set_ex& value, uint32_t depth = 0 ); +// +////template< typename Stream, typename Storage > +////inline void pack( Stream& s, const hive::protocol::fixed_string_impl< Storage >& u ); +////template< typename Stream, typename Storage > +////inline void unpack( Stream& s, hive::protocol::fixed_string_impl< Storage >& u, uint32_t depth = 0 ); +// +//template +//inline void pack(Stream &s, const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t depth = 0); +//template +//inline void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t depth = 0); +// +////template< typename Stream > +////inline void pack( Stream& s, const hive::protocol::legacy_hive_asset_symbol_type& sym ); +////template< typename Stream > +////inline void unpack( Stream& s, hive::protocol::legacy_hive_asset_symbol_type& sym, uint32_t depth = 0 ); +// +//} // namespace raw +// +////template +////void to_variant( const flat_set_ex& var, variant& vo ); +// +////template +////void from_variant( const variant& var, flat_set_ex& vo ); +// +////template< typename Storage > +////inline void to_variant( const hive::protocol::fixed_string_impl< Storage >& s, fc::variant& v ); +////template< typename Storage > +////inline void from_variant( const variant& v, hive::protocol::fixed_string_impl< Storage >& s ); +// +//inline void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &v, uint32_t max_depth); +// +////inline void from_variant( const fc::variant& v, hive::protocol::legacy_hive_asset& leg ); +////inline void to_variant( const hive::protocol::legacy_hive_asset& leg, fc::variant& v ); +// +////template struct get_typename> +////{ +//// static const char* name() { +//// static std::string n = std::string("flat_set<") + get_typename< fc::flat_set >::name() + ">"; +//// return n.c_str(); +//// } +////}; +// +//} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index ca0e6df7..7790faee 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -168,10 +168,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ bool enable_peerplays_asset_deposits = false; #ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS - enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) && - (sed.sidechain_currency.compare("BTC") != 0) && - (sed.sidechain_currency.compare("HBD") != 0) && - (sed.sidechain_currency.compare("HIVE") != 0); + //enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) && + // (sed.sidechain_currency.compare("BTC") != 0) && + // (sed.sidechain_currency.compare("HBD") != 0) && + // (sed.sidechain_currency.compare("HIVE") != 0); #endif bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) && @@ -180,10 +180,19 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) || enable_peerplays_asset_deposits); + bool is_tracked_asset = false; + if (sed.sidechain == sidechain_type::peerplays) { + for (const auto &asset_id : tracked_assets) { + std::string asset_id_str = asset_id_to_string(asset_id); + if (sed.sidechain_currency == asset_id_str) { + is_tracked_asset = true; + break; + } + } + } + bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) && - ((sed.sidechain_currency.compare("BTC") == 0) || - (sed.sidechain_currency.compare("HBD") == 0) || - (sed.sidechain_currency.compare("HIVE") == 0)); + is_tracked_asset; // Deposit request if (deposit_condition) { @@ -223,12 +232,29 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ // Withdrawal request if (withdraw_condition) { - // BTC Payout only (for now) const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain_type::bitcoin, time_point_sec::maximum())); + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain, time_point_sec::maximum())); if (addr_itr == sidechain_addresses_idx.end()) return; + std::string withdraw_currency = ""; + price withdraw_currency_price = {}; + if (sed.sidechain_currency == asset_id_to_string(gpo.parameters.btc_asset())) { + withdraw_currency = "BTC"; + withdraw_currency_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + } + if (sed.sidechain_currency == asset_id_to_string(gpo.parameters.hbd_asset())) { + withdraw_currency = "HBD"; + withdraw_currency_price = database.get(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate; + } + if (sed.sidechain_currency == asset_id_to_string(gpo.parameters.hive_asset())) { + withdraw_currency = "HIVE"; + withdraw_currency_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; + } + if (withdraw_currency.empty()) { + return; + } + for (son_id_type son_id : plugin.get_sons()) { if (plugin.is_active_son(son_id)) { @@ -242,12 +268,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ op.peerplays_transaction_id = sed.sidechain_transaction_id; op.peerplays_from = sed.peerplays_from; op.peerplays_asset = sed.peerplays_asset; - // BTC payout only (for now) - op.withdraw_sidechain = sidechain_type::bitcoin; + op.withdraw_sidechain = sidechain; op.withdraw_address = addr_itr->withdraw_address; - op.withdraw_currency = "BTC"; - price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; - op.withdraw_amount = sed.peerplays_asset.amount * btc_price.quote.amount / btc_price.base.amount; + op.withdraw_currency = withdraw_currency; + op.withdraw_amount = sed.peerplays_asset.amount * withdraw_currency_price.quote.amount / withdraw_currency_price.base.amount; signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), op); try { @@ -593,6 +617,7 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) { operation_index = operation_index + 1; if (op.which() == operation::tag::value) { transfer_operation transfer_op = op.get(); + if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) { continue; } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 1698ef8b..e669491a 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -472,6 +472,78 @@ bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object } bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_object &swwo) { + + const chain::global_property_object &gpo = database.get_global_properties(); + + //===== + + uint32_t asset_num = 0; + if (swwo.withdraw_currency == "HBD") { + asset_num = HIVE_ASSET_NUM_HBD; + } + if (swwo.withdraw_currency == "HIVE") { + asset_num = HIVE_ASSET_NUM_HIVE; + } + + hive::transfer_operation t_op; + t_op.from = "son-account"; + t_op.to = swwo.withdraw_address; + t_op.amount.amount = swwo.withdraw_amount; + t_op.amount.symbol = hive::asset_symbol_type::from_asset_num(asset_num); + t_op.memo = ""; + + std::string block_id_str = node_rpc_client->get_head_block_id(); + hive::block_id_type head_block_id(block_id_str); + + std::string head_block_time_str = node_rpc_client->get_head_block_time(); + time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str); + + hive::signed_transaction htrx; + htrx.set_reference_block(head_block_id); + htrx.set_expiration(head_block_time + fc::seconds(90)); + + htrx.operations.push_back(t_op); + ilog("TRX: ${htrx}", ("htrx", htrx)); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + std::string tx_str = boost::algorithm::hex(ss.str()); + if (tx_str.empty()) { + return false; + } + + //===== + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + 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); + + son_wallet_withdraw_process_operation swwp_op; + swwp_op.payer = gpo.parameters.son_account(); + swwp_op.son_wallet_withdraw_id = swwo.id; + proposal_op.proposed_ops.emplace_back(swwp_op); + + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = swwo.id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + proposal_op.proposed_ops.emplace_back(stc_op); + + 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; } @@ -635,6 +707,42 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { } } } + + //========== + { + hive::transfer_operation t_op; + t_op.from = "sonaccount01"; + t_op.to = "account05"; + t_op.amount.amount = 1000; + t_op.amount.symbol = hive::asset_symbol_type::from_asset_num(HIVE_ASSET_NUM_HIVE); + t_op.memo = ""; + + std::string block_id_str = node_rpc_client->get_head_block_id(); + hive::block_id_type head_block_id(block_id_str); + //hive::block_id_type head_block_id("000087723a5513e7cc0f03a71bf05a5b7b36102f"); + + std::string head_block_time_str = node_rpc_client->get_head_block_time(); + time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str); + //time_point head_block_time = fc::time_point_sec::from_iso_string("2021-04-23T10:38:03"); + + hive::signed_transaction htrx; + htrx.set_reference_block(head_block_id); + htrx.set_expiration(head_block_time + fc::seconds(30)); + + htrx.operations.push_back(t_op); + ilog("TRX: ${htrx}", ("htrx", htrx)); + + std::string chain_id_str = node_rpc_client->get_chain_id(); + const hive::chain_id_type chain_id(chain_id_str); + + fc::optional privkey = graphene::utilities::wif_to_key(get_private_key("sonaccount01")); + htrx.sign(*privkey, chain_id); + + std::string params = fc::json::to_string(htrx); + ilog("HTRX: ${htrx}", ("htrx", params)); + node_rpc_client->network_broadcast_api_broadcast_transaction(params); + } + //========== } }} // namespace graphene::peerplays_sidechain -- 2.45.2 From c6a7ab20571c1c811d874bda8fc066e81d15c977 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 19 May 2021 19:43:19 +0200 Subject: [PATCH 16/57] Fix Hive transaction serialization --- README.md | 1 - .../peerplays_sidechain/hive/asset.cpp | 224 +------------ .../peerplays_sidechain/hive/asset_symbol.cpp | 300 ------------------ .../peerplays_sidechain/hive/asset.hpp | 23 +- .../peerplays_sidechain/hive/asset_symbol.hpp | 245 -------------- .../sidechain_net_handler_hive.cpp | 45 +-- .../sidechain_net_manager.cpp | 6 +- 7 files changed, 31 insertions(+), 813 deletions(-) delete mode 100644 libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp delete mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp diff --git a/README.md b/README.md index 7173bcb1..e1ad6ef0 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,6 @@ make -j$(nproc) make install # this can install the executable files under /usr/local ``` -docker build -t peerplays . ## Docker image diff --git a/libraries/plugins/peerplays_sidechain/hive/asset.cpp b/libraries/plugins/peerplays_sidechain/hive/asset.cpp index e27c0494..9adefe94 100644 --- a/libraries/plugins/peerplays_sidechain/hive/asset.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/asset.cpp @@ -9,231 +9,11 @@ #define ASSET_PRECISION_KEY "precision" #define ASSET_NAI_KEY "nai" -namespace graphene { namespace peerplays_sidechain { namespace hive { - -std::string asset_symbol_type::to_string() const { - return fc::json::to_string(fc::variant(*this, 5)); -} - -asset_symbol_type asset_symbol_type::from_string(const std::string &str) { - return fc::json::from_string(str).as(5); -} - -void asset_symbol_type::to_nai_string(char *buf) const { - static_assert(HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH >= 12, "This code will overflow a short buffer"); - uint32_t x = to_nai(); - buf[11] = '\0'; - buf[10] = ((x % 10) + '0'); - x /= 10; - buf[9] = ((x % 10) + '0'); - x /= 10; - buf[8] = ((x % 10) + '0'); - x /= 10; - buf[7] = ((x % 10) + '0'); - x /= 10; - buf[6] = ((x % 10) + '0'); - x /= 10; - buf[5] = ((x % 10) + '0'); - x /= 10; - buf[4] = ((x % 10) + '0'); - x /= 10; - buf[3] = ((x % 10) + '0'); - x /= 10; - buf[2] = ((x) + '0'); - buf[1] = '@'; - buf[0] = '@'; -} - -asset_symbol_type asset_symbol_type::from_nai_string(const char *p, uint8_t decimal_places) { - try { - FC_ASSERT(p != nullptr, "NAI string cannot be a null"); - FC_ASSERT(std::strlen(p) == HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - 1, "Incorrect NAI string length"); - FC_ASSERT(p[0] == '@' && p[1] == '@', "Invalid NAI string prefix"); - uint32_t nai = boost::lexical_cast(p + 2); - return asset_symbol_type::from_nai(nai, decimal_places); - } - FC_CAPTURE_AND_RETHROW(); -} - -// Highly optimized implementation of Damm algorithm -// https://en.wikipedia.org/wiki/Damm_algorithm -uint8_t asset_symbol_type::damm_checksum_8digit(uint32_t value) { - FC_ASSERT(value < 100000000); - - const uint8_t t[] = { - 0, 30, 10, 70, 50, 90, 80, 60, 40, 20, - 70, 0, 90, 20, 10, 50, 40, 80, 60, 30, - 40, 20, 0, 60, 80, 70, 10, 30, 50, 90, - 10, 70, 50, 0, 90, 80, 30, 40, 20, 60, - 60, 10, 20, 30, 0, 40, 50, 90, 70, 80, - 30, 60, 70, 40, 20, 0, 90, 50, 80, 10, - 50, 80, 60, 90, 70, 20, 0, 10, 30, 40, - 80, 90, 40, 50, 30, 60, 20, 0, 10, 70, - 90, 40, 30, 80, 60, 10, 70, 20, 0, 50, - 20, 50, 80, 10, 40, 30, 60, 70, 90, 0}; - - uint32_t q0 = value / 10; - uint32_t d0 = value % 10; - uint32_t q1 = q0 / 10; - uint32_t d1 = q0 % 10; - uint32_t q2 = q1 / 10; - uint32_t d2 = q1 % 10; - uint32_t q3 = q2 / 10; - uint32_t d3 = q2 % 10; - uint32_t q4 = q3 / 10; - uint32_t d4 = q3 % 10; - uint32_t q5 = q4 / 10; - uint32_t d5 = q4 % 10; - uint32_t d6 = q5 % 10; - uint32_t d7 = q5 / 10; - - uint8_t x = t[d7]; - x = t[x + d6]; - x = t[x + d5]; - x = t[x + d4]; - x = t[x + d3]; - x = t[x + d2]; - x = t[x + d1]; - x = t[x + d0]; - return x / 10; -} - -uint32_t asset_symbol_type::asset_num_from_nai(uint32_t nai, uint8_t decimal_places) { - // Can be replaced with some clever bitshifting - uint32_t nai_check_digit = nai % 10; - uint32_t nai_data_digits = nai / 10; - - FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & (nai_data_digits <= SMT_MAX_NAI), "NAI out of range"); - FC_ASSERT(nai_check_digit == damm_checksum_8digit(nai_data_digits), "Invalid check digit"); - - switch (nai_data_digits) { - case HIVE_NAI_HIVE: - FC_ASSERT(decimal_places == HIVE_PRECISION_HIVE); - return HIVE_ASSET_NUM_HIVE; - case HIVE_NAI_HBD: - FC_ASSERT(decimal_places == HIVE_PRECISION_HBD); - return HIVE_ASSET_NUM_HBD; - case HIVE_NAI_VESTS: - FC_ASSERT(decimal_places == HIVE_PRECISION_VESTS); - return HIVE_ASSET_NUM_VESTS; - default: - FC_ASSERT(decimal_places <= HIVE_ASSET_MAX_DECIMALS, "Invalid decimal_places"); - return (nai_data_digits << HIVE_NAI_SHIFT) | SMT_ASSET_NUM_CONTROL_MASK | decimal_places; - } -} - -uint32_t asset_symbol_type::to_nai() const { - uint32_t nai_data_digits = 0; - - // Can be replaced with some clever bitshifting - switch (asset_num) { - case HIVE_ASSET_NUM_HIVE: - nai_data_digits = HIVE_NAI_HIVE; - break; - case HIVE_ASSET_NUM_HBD: - nai_data_digits = HIVE_NAI_HBD; - break; - case HIVE_ASSET_NUM_VESTS: - nai_data_digits = HIVE_NAI_VESTS; - break; - default: - FC_ASSERT(space() == smt_nai_space); - nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); - } - - uint32_t nai_check_digit = damm_checksum_8digit(nai_data_digits); - return nai_data_digits * 10 + nai_check_digit; -} - -bool asset_symbol_type::is_vesting() const { - switch (space()) { - case legacy_space: { - switch (asset_num) { - case HIVE_ASSET_NUM_HIVE: - return false; - case HIVE_ASSET_NUM_HBD: - // HBD is certainly liquid. - return false; - case HIVE_ASSET_NUM_VESTS: - return true; - default: - FC_ASSERT(false, "Unknown asset symbol"); - } - } - case smt_nai_space: - // 6th bit of asset_num is used as vesting/liquid variant indicator. - return asset_num & SMT_ASSET_NUM_VESTING_MASK; - default: - FC_ASSERT(false, "Unknown asset symbol"); - } -} - -asset_symbol_type asset_symbol_type::get_paired_symbol() const { - switch (space()) { - case legacy_space: { - switch (asset_num) { - case HIVE_ASSET_NUM_HIVE: - return from_asset_num(HIVE_ASSET_NUM_VESTS); - case HIVE_ASSET_NUM_HBD: - return *this; - case HIVE_ASSET_NUM_VESTS: - return from_asset_num(HIVE_ASSET_NUM_HIVE); - default: - FC_ASSERT(false, "Unknown asset symbol"); - } - } - case smt_nai_space: { - // Toggle 6th bit of this asset_num. - auto paired_asset_num = asset_num ^ (SMT_ASSET_NUM_VESTING_MASK); - return from_asset_num(paired_asset_num); - } - default: - FC_ASSERT(false, "Unknown asset symbol"); - } -} - -asset_symbol_type::asset_symbol_space asset_symbol_type::space() const { - asset_symbol_type::asset_symbol_space s = legacy_space; - switch (asset_num) { - case HIVE_ASSET_NUM_HIVE: - case HIVE_ASSET_NUM_HBD: - case HIVE_ASSET_NUM_VESTS: - s = legacy_space; - break; - default: - s = smt_nai_space; - } - return s; -} - -void asset_symbol_type::validate() const { - switch (asset_num) { - case HIVE_ASSET_NUM_HIVE: - case HIVE_ASSET_NUM_HBD: - case HIVE_ASSET_NUM_VESTS: - break; - default: { - uint32_t nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); - uint32_t nai_1bit = (asset_num & SMT_ASSET_NUM_CONTROL_MASK); - uint32_t nai_decimal_places = (asset_num & SMT_ASSET_NUM_PRECISION_MASK); - FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & - (nai_data_digits <= SMT_MAX_NAI) & - (nai_1bit == SMT_ASSET_NUM_CONTROL_MASK) & - (nai_decimal_places <= HIVE_ASSET_MAX_DECIMALS), - "Cannot determine space for asset ${n}", ("n", asset_num)); - } - } - // this assert is duplicated by above code in all cases - // FC_ASSERT( decimals() <= HIVE_ASSET_MAX_DECIMALS ); -} - -}}} // namespace graphene::peerplays_sidechain::hive - namespace fc { void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth) { try { - variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(var.symbol.decimals()))(ASSET_NAI_KEY, var.symbol.to_nai_string()); + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(TESTS_PRECISION))(ASSET_NAI_KEY, TESTS_NAI); vo = v; } FC_CAPTURE_AND_RETHROW() @@ -256,7 +36,7 @@ void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::a FC_ASSERT(v_object.contains(ASSET_NAI_KEY), "NAI field doesn't exist."); FC_ASSERT(v_object[ASSET_NAI_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_NAI_KEY)); - vo.symbol = graphene::peerplays_sidechain::hive::asset_symbol_type::from_nai_string(v_object[ASSET_NAI_KEY].as(max_depth).c_str(), v_object[ASSET_PRECISION_KEY].as(max_depth)); + vo.symbol = TESTS_SYMBOL_SER; } FC_CAPTURE_AND_RETHROW() } diff --git a/libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp b/libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp deleted file mode 100644 index a44b9138..00000000 --- a/libraries/plugins/peerplays_sidechain/hive/asset_symbol.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//#include -// -//#include -// -//namespace graphene { namespace peerplays_sidechain { namespace hive { -// -//std::string asset_symbol_type::to_string() const { -// return fc::json::to_string(fc::variant(*this, 5)); -//} -// -//asset_symbol_type asset_symbol_type::from_string(const std::string &str) { -// return fc::json::from_string(str).as(5); -//} -// -//void asset_symbol_type::to_nai_string(char *buf) const { -// static_assert(HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH >= 12, "This code will overflow a short buffer"); -// uint32_t x = to_nai(); -// buf[11] = '\0'; -// buf[10] = ((x % 10) + '0'); -// x /= 10; -// buf[9] = ((x % 10) + '0'); -// x /= 10; -// buf[8] = ((x % 10) + '0'); -// x /= 10; -// buf[7] = ((x % 10) + '0'); -// x /= 10; -// buf[6] = ((x % 10) + '0'); -// x /= 10; -// buf[5] = ((x % 10) + '0'); -// x /= 10; -// buf[4] = ((x % 10) + '0'); -// x /= 10; -// buf[3] = ((x % 10) + '0'); -// x /= 10; -// buf[2] = ((x) + '0'); -// buf[1] = '@'; -// buf[0] = '@'; -//} -// -//asset_symbol_type asset_symbol_type::from_nai_string(const char *p, uint8_t decimal_places) { -// try { -// FC_ASSERT(p != nullptr, "NAI string cannot be a null"); -// FC_ASSERT(std::strlen(p) == HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - 1, "Incorrect NAI string length"); -// FC_ASSERT(p[0] == '@' && p[1] == '@', "Invalid NAI string prefix"); -// uint32_t nai = boost::lexical_cast(p + 2); -// return asset_symbol_type::from_nai(nai, decimal_places); -// } -// FC_CAPTURE_AND_RETHROW(); -//} -// -//// Highly optimized implementation of Damm algorithm -//// https://en.wikipedia.org/wiki/Damm_algorithm -//uint8_t asset_symbol_type::damm_checksum_8digit(uint32_t value) { -// FC_ASSERT(value < 100000000); -// -// const uint8_t t[] = { -// 0, 30, 10, 70, 50, 90, 80, 60, 40, 20, -// 70, 0, 90, 20, 10, 50, 40, 80, 60, 30, -// 40, 20, 0, 60, 80, 70, 10, 30, 50, 90, -// 10, 70, 50, 0, 90, 80, 30, 40, 20, 60, -// 60, 10, 20, 30, 0, 40, 50, 90, 70, 80, -// 30, 60, 70, 40, 20, 0, 90, 50, 80, 10, -// 50, 80, 60, 90, 70, 20, 0, 10, 30, 40, -// 80, 90, 40, 50, 30, 60, 20, 0, 10, 70, -// 90, 40, 30, 80, 60, 10, 70, 20, 0, 50, -// 20, 50, 80, 10, 40, 30, 60, 70, 90, 0}; -// -// uint32_t q0 = value / 10; -// uint32_t d0 = value % 10; -// uint32_t q1 = q0 / 10; -// uint32_t d1 = q0 % 10; -// uint32_t q2 = q1 / 10; -// uint32_t d2 = q1 % 10; -// uint32_t q3 = q2 / 10; -// uint32_t d3 = q2 % 10; -// uint32_t q4 = q3 / 10; -// uint32_t d4 = q3 % 10; -// uint32_t q5 = q4 / 10; -// uint32_t d5 = q4 % 10; -// uint32_t d6 = q5 % 10; -// uint32_t d7 = q5 / 10; -// -// uint8_t x = t[d7]; -// x = t[x + d6]; -// x = t[x + d5]; -// x = t[x + d4]; -// x = t[x + d3]; -// x = t[x + d2]; -// x = t[x + d1]; -// x = t[x + d0]; -// return x / 10; -//} -// -//uint32_t asset_symbol_type::asset_num_from_nai(uint32_t nai, uint8_t decimal_places) { -// // Can be replaced with some clever bitshifting -// uint32_t nai_check_digit = nai % 10; -// uint32_t nai_data_digits = nai / 10; -// -// FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & (nai_data_digits <= SMT_MAX_NAI), "NAI out of range"); -// FC_ASSERT(nai_check_digit == damm_checksum_8digit(nai_data_digits), "Invalid check digit"); -// -// switch (nai_data_digits) { -// case HIVE_NAI_HIVE: -// FC_ASSERT(decimal_places == HIVE_PRECISION_HIVE); -// return HIVE_ASSET_NUM_HIVE; -// case HIVE_NAI_HBD: -// FC_ASSERT(decimal_places == HIVE_PRECISION_HBD); -// return HIVE_ASSET_NUM_HBD; -// case HIVE_NAI_VESTS: -// FC_ASSERT(decimal_places == HIVE_PRECISION_VESTS); -// return HIVE_ASSET_NUM_VESTS; -// default: -// FC_ASSERT(decimal_places <= HIVE_ASSET_MAX_DECIMALS, "Invalid decimal_places"); -// return (nai_data_digits << HIVE_NAI_SHIFT) | SMT_ASSET_NUM_CONTROL_MASK | decimal_places; -// } -//} -// -//uint32_t asset_symbol_type::to_nai() const { -// uint32_t nai_data_digits = 0; -// -// // Can be replaced with some clever bitshifting -// switch (asset_num) { -// case HIVE_ASSET_NUM_HIVE: -// nai_data_digits = HIVE_NAI_HIVE; -// break; -// case HIVE_ASSET_NUM_HBD: -// nai_data_digits = HIVE_NAI_HBD; -// break; -// case HIVE_ASSET_NUM_VESTS: -// nai_data_digits = HIVE_NAI_VESTS; -// break; -// default: -// FC_ASSERT(space() == smt_nai_space); -// nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); -// } -// -// uint32_t nai_check_digit = damm_checksum_8digit(nai_data_digits); -// return nai_data_digits * 10 + nai_check_digit; -//} -// -//bool asset_symbol_type::is_vesting() const { -// switch (space()) { -// case legacy_space: { -// switch (asset_num) { -// case HIVE_ASSET_NUM_HIVE: -// return false; -// case HIVE_ASSET_NUM_HBD: -// // HBD is certainly liquid. -// return false; -// case HIVE_ASSET_NUM_VESTS: -// return true; -// default: -// FC_ASSERT(false, "Unknown asset symbol"); -// } -// } -// case smt_nai_space: -// // 6th bit of asset_num is used as vesting/liquid variant indicator. -// return asset_num & SMT_ASSET_NUM_VESTING_MASK; -// default: -// FC_ASSERT(false, "Unknown asset symbol"); -// } -//} -// -//asset_symbol_type asset_symbol_type::get_paired_symbol() const { -// switch (space()) { -// case legacy_space: { -// switch (asset_num) { -// case HIVE_ASSET_NUM_HIVE: -// return from_asset_num(HIVE_ASSET_NUM_VESTS); -// case HIVE_ASSET_NUM_HBD: -// return *this; -// case HIVE_ASSET_NUM_VESTS: -// return from_asset_num(HIVE_ASSET_NUM_HIVE); -// default: -// FC_ASSERT(false, "Unknown asset symbol"); -// } -// } -// case smt_nai_space: { -// // Toggle 6th bit of this asset_num. -// auto paired_asset_num = asset_num ^ (SMT_ASSET_NUM_VESTING_MASK); -// return from_asset_num(paired_asset_num); -// } -// default: -// FC_ASSERT(false, "Unknown asset symbol"); -// } -//} -// -//asset_symbol_type::asset_symbol_space asset_symbol_type::space() const { -// asset_symbol_type::asset_symbol_space s = legacy_space; -// switch (asset_num) { -// case HIVE_ASSET_NUM_HIVE: -// case HIVE_ASSET_NUM_HBD: -// case HIVE_ASSET_NUM_VESTS: -// s = legacy_space; -// break; -// default: -// s = smt_nai_space; -// } -// return s; -//} -// -//void asset_symbol_type::validate() const { -// switch (asset_num) { -// case HIVE_ASSET_NUM_HIVE: -// case HIVE_ASSET_NUM_HBD: -// case HIVE_ASSET_NUM_VESTS: -// break; -// default: { -// uint32_t nai_data_digits = (asset_num >> HIVE_NAI_SHIFT); -// uint32_t nai_1bit = (asset_num & SMT_ASSET_NUM_CONTROL_MASK); -// uint32_t nai_decimal_places = (asset_num & SMT_ASSET_NUM_PRECISION_MASK); -// FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & -// (nai_data_digits <= SMT_MAX_NAI) & -// (nai_1bit == SMT_ASSET_NUM_CONTROL_MASK) & -// (nai_decimal_places <= HIVE_ASSET_MAX_DECIMALS), -// "Cannot determine space for asset ${n}", ("n", asset_num)); -// } -// } -// // this assert is duplicated by above code in all cases -// // FC_ASSERT( decimals() <= HIVE_ASSET_MAX_DECIMALS ); -//} -// -//}}} // namespace graphene::peerplays_sidechain::hive -// -//namespace fc { -// -//namespace raw { -// -//// Legacy serialization of assets -//// 0000pppp aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff 00000000 -//// Symbol = abcdef -//// -//// NAI serialization of assets -//// aaa1pppp bbbbbbbb cccccccc dddddddd -//// NAI = (MSB to LSB) dddddddd cccccccc bbbbbbbb aaa -//// -//// NAI internal storage of legacy assets -// -////template -////void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t, uint32_t max_depth) { -//// uint64_t ser = 0; -//// s.read((char *)&ser, 4); -//// -//// switch (ser) { -//// case OBSOLETE_SYMBOL_SER & 0xFFFFFFFF: -//// s.read(((char *)&ser) + 4, 4); -//// FC_ASSERT(ser == OBSOLETE_SYMBOL_SER, "invalid asset bits"); -//// sym.asset_num = HIVE_ASSET_NUM_HIVE; -//// break; -//// case OBD_SYMBOL_SER & 0xFFFFFFFF: -//// s.read(((char *)&ser) + 4, 4); -//// FC_ASSERT(ser == OBD_SYMBOL_SER, "invalid asset bits"); -//// sym.asset_num = HIVE_ASSET_NUM_HBD; -//// break; -//// case VESTS_SYMBOL_SER & 0xFFFFFFFF: -//// s.read(((char *)&ser) + 4, 4); -//// FC_ASSERT(ser == VESTS_SYMBOL_SER, "invalid asset bits"); -//// sym.asset_num = HIVE_ASSET_NUM_VESTS; -//// break; -//// default: -//// sym.asset_num = uint32_t(ser); -//// } -//// sym.validate(); -////} -// -//} // namespace raw -//// -////void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &var, uint32_t max_depth) { -//// try { -//// mutable_variant_object o; -//// o(ASSET_SYMBOL_NAI_KEY, sym.to_nai_string())(ASSET_SYMBOL_DECIMALS_KEY, sym.decimals()); -//// var = std::move(o); -//// } -//// FC_CAPTURE_AND_RETHROW() -////} -//// -////void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t max_depth) { -//// using graphene::peerplays_sidechain::hive::asset_symbol_type; -//// -//// try { -//// FC_ASSERT(var.is_object(), "Asset symbol is expected to be an object."); -//// -//// auto &o = var.get_object(); -//// -//// auto nai = o.find(ASSET_SYMBOL_NAI_KEY); -//// FC_ASSERT(nai != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); -//// FC_ASSERT(nai->value().is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); -//// -//// auto decimals = o.find(ASSET_SYMBOL_DECIMALS_KEY); -//// FC_ASSERT(decimals != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); -//// FC_ASSERT(decimals->value().is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); -//// FC_ASSERT(decimals->value().as_uint64() <= HIVE_ASSET_MAX_DECIMALS, -//// "Expected decimals to be less than or equal to ${num}", ("num", HIVE_ASSET_MAX_DECIMALS)); -//// -//// sym = asset_symbol_type::from_nai_string(nai->value().as_string().c_str(), decimals->value().as(max_depth)); -//// } -//// FC_CAPTURE_AND_RETHROW() -////} -// -//} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp index aaab642f..8b526e35 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp @@ -1,13 +1,32 @@ #pragma once -#include #include namespace graphene { namespace peerplays_sidechain { namespace hive { +#define HBD_NAI "@@000000013" +#define HBD_PRECISION 3 +#define HBD_SYMBOL_U64 (uint64_t('H') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define HBD_SYMBOL_SER (uint64_t(3) | (HBD_SYMBOL_U64 << 8)) + +#define HIVE_NAI "@@000000021" +#define HIVE_PRECISION 3 +#define HIVE_SYMBOL_U64 (uint64_t('H') | (uint64_t('I') << 8) | (uint64_t('V') << 16) | (uint64_t('E') << 24)) +#define HIVE_SYMBOL_SER (uint64_t(3) | (HIVE_SYMBOL_U64 << 8)) + +#define TBD_NAI "@@000000013" +#define TBD_PRECISION 3 +#define TBD_SYMBOL_U64 (uint64_t('T') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define TBD_SYMBOL_SER (uint64_t(3) | (TBD_SYMBOL_U64 << 8)) + +#define TESTS_NAI "@@000000021" +#define TESTS_PRECISION 3 +#define TESTS_SYMBOL_U64 (uint64_t('T') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32)) +#define TESTS_SYMBOL_SER (uint64_t(3) | (TESTS_SYMBOL_U64 << 8)) + struct asset { share_type amount; - asset_symbol_type symbol; + uint64_t symbol; }; }}} // namespace graphene::peerplays_sidechain::hive diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp deleted file mode 100644 index 4eb1d9b0..00000000 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset_symbol.hpp +++ /dev/null @@ -1,245 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define HIVE_ASSET_SYMBOL_PRECISION_BITS 4 -#define HIVE_ASSET_CONTROL_BITS 1 -#define HIVE_NAI_SHIFT (HIVE_ASSET_SYMBOL_PRECISION_BITS + HIVE_ASSET_CONTROL_BITS) -#define SMT_MAX_NAI 99999999 -#define SMT_MIN_NAI 1 -#define SMT_MIN_NON_RESERVED_NAI 10000000 -#define HIVE_ASSET_SYMBOL_NAI_LENGTH 10 -#define HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH (HIVE_ASSET_SYMBOL_NAI_LENGTH + 2) -#define SMT_MAX_NAI_POOL_COUNT 10 -#define SMT_MAX_NAI_GENERATION_TRIES 100 - -#define HIVE_PRECISION_HBD (3) -#define HIVE_PRECISION_HIVE (3) -#define HIVE_PRECISION_VESTS (6) - -// One's place is used for check digit, which means NAI 0-9 all have NAI data of 0 which is invalid -// This space is safe to use because it would alwasys result in failure to convert from NAI -#define HIVE_NAI_HBD (1) -#define HIVE_NAI_HIVE (2) -#define HIVE_NAI_VESTS (3) - -#define HIVE_ASSET_NUM_HBD (uint32_t(((SMT_MAX_NAI + HIVE_NAI_HBD) << HIVE_NAI_SHIFT) | HIVE_PRECISION_HBD)) -#define HIVE_ASSET_NUM_HIVE (uint32_t(((SMT_MAX_NAI + HIVE_NAI_HIVE) << HIVE_NAI_SHIFT) | HIVE_PRECISION_HIVE)) -#define HIVE_ASSET_NUM_VESTS (uint32_t(((SMT_MAX_NAI + HIVE_NAI_VESTS) << HIVE_NAI_SHIFT) | HIVE_PRECISION_VESTS)) - -#ifdef IS_TEST_NET - -#define VESTS_SYMBOL_U64 (uint64_t('V') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32)) -my #define HIVE_SYMBOL_U64 OBSOLETE_SYMBOL_U64 -#define OBD_SYMBOL_U64 (uint64_t('T') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) -#define HBD_SYMBOL_U64 OBD_SYMBOL_U64 -#else - -#define VESTS_SYMBOL_U64 (uint64_t('V') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32)) -#define OBSOLETE_SYMBOL_U64 (uint64_t('S') | (uint64_t('T') << 8) | (uint64_t('E') << 16) | (uint64_t('E') << 24) | (uint64_t('M') << 32)) -#define HIVE_SYMBOL_U64 (uint64_t('H') | (uint64_t('I') << 8) | (uint64_t('V') << 16) | (uint64_t('E') << 24)) -#define OBD_SYMBOL_U64 (uint64_t('S') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) -#define HBD_SYMBOL_U64 (uint64_t('H') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) - -#endif - -#define VESTS_SYMBOL_SER (uint64_t(6) | (VESTS_SYMBOL_U64 << 8)) ///< VESTS|VESTS with 6 digits of precision -#define OBSOLETE_SYMBOL_SER (uint64_t(3) | (OBSOLETE_SYMBOL_U64 << 8)) ///< STEEM|TESTS with 3 digits of precision -#define OBD_SYMBOL_SER (uint64_t(3) | (OBD_SYMBOL_U64 << 8)) ///< SBD|TBD with 3 digits of precision - -#define HIVE_ASSET_MAX_DECIMALS 12 - -#define SMT_ASSET_NUM_PRECISION_MASK 0xF -#define SMT_ASSET_NUM_CONTROL_MASK 0x10 -#define SMT_ASSET_NUM_VESTING_MASK 0x20 - -#define ASSET_SYMBOL_NAI_KEY "nai" -#define ASSET_SYMBOL_DECIMALS_KEY "decimals" - - namespace graphene { - namespace peerplays_sidechain { namespace hive { - - class asset_symbol_type { - public: - enum asset_symbol_space { - legacy_space = 1, - smt_nai_space = 2 - }; - - explicit operator uint32_t() { - return to_nai(); - } - - static asset_symbol_type from_string(const std::string &str); - // buf must have space for HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - static asset_symbol_type from_nai_string(const char *buf, uint8_t decimal_places); - static asset_symbol_type from_asset_num(uint32_t asset_num) { - asset_symbol_type result; - result.asset_num = asset_num; - return result; - } - static uint32_t asset_num_from_nai(uint32_t nai, uint8_t decimal_places); - static asset_symbol_type from_nai(uint32_t nai, uint8_t decimal_places) { - return from_asset_num(asset_num_from_nai(nai, decimal_places)); - } - static uint8_t damm_checksum_8digit(uint32_t value); - - std::string to_string() const; - - void to_nai_string(char *buf) const; - std::string to_nai_string() const { - char buf[HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH]; - to_nai_string(buf); - return std::string(buf); - } - - uint32_t to_nai() const; - - /**Returns true when symbol represents vesting variant of the token, - * false for liquid one. - */ - bool is_vesting() const; - /**Returns vesting symbol when called from liquid one - * and liquid symbol when called from vesting one. - * Returns back the HBD symbol if represents HBD. - */ - asset_symbol_type get_paired_symbol() const; - /**Returns asset_num stripped of precision holding bits. - * \warning checking that it's SMT symbol is caller responsibility. - */ - uint32_t get_stripped_precision_smt_num() const { - return asset_num & ~(SMT_ASSET_NUM_PRECISION_MASK); - } - - asset_symbol_space space() const; - uint8_t decimals() const { - return uint8_t(asset_num & SMT_ASSET_NUM_PRECISION_MASK); - } - - void validate() const; - - uint32_t asset_num = 0; - uint64_t ser = OBSOLETE_SYMBOL_SER; - }; - - }} // namespace peerplays_sidechain::hive -} // namespace graphene - -FC_REFLECT(graphene::peerplays_sidechain::hive::asset_symbol_type, (asset_num)) - -namespace fc { - -namespace raw { - -// Legacy serialization of assets -// 0000pppp aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff 00000000 -// Symbol = abcdef -// -// NAI serialization of assets -// aaa1pppp bbbbbbbb cccccccc dddddddd -// NAI = (MSB to LSB) dddddddd cccccccc bbbbbbbb aaa -// -// NAI internal storage of legacy assets - -template -void pack(Stream &s, const graphene::peerplays_sidechain::hive::asset_symbol_type &sym) { - std::cout << "##### PACK ###" << std::endl; - switch (sym.space()) { - case graphene::peerplays_sidechain::hive::asset_symbol_type::legacy_space: { - uint64_t ser = 0; - switch (sym.asset_num) { - case HIVE_ASSET_NUM_HIVE: - ser = OBSOLETE_SYMBOL_SER; - break; - case HIVE_ASSET_NUM_HBD: - ser = OBD_SYMBOL_SER; - break; - case HIVE_ASSET_NUM_VESTS: - ser = VESTS_SYMBOL_SER; - break; - default: - FC_ASSERT(false, "Cannot serialize unknown asset symbol"); - } - pack(s, ser); - break; - } - case graphene::peerplays_sidechain::hive::asset_symbol_type::smt_nai_space: - pack(s, sym.asset_num); - break; - default: - FC_ASSERT(false, "Cannot serialize unknown asset symbol"); - } -} - -template -void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym) { - std::cout << "##### UNPACK ###" << std::endl; - uint64_t ser = 0; - s.read((char *)&ser, 4); - - switch (ser) { - case OBSOLETE_SYMBOL_SER & 0xFFFFFFFF: - s.read(((char *)&ser) + 4, 4); - FC_ASSERT(ser == OBSOLETE_SYMBOL_SER, "invalid asset bits"); - sym.asset_num = HIVE_ASSET_NUM_HIVE; - break; - case OBD_SYMBOL_SER & 0xFFFFFFFF: - s.read(((char *)&ser) + 4, 4); - FC_ASSERT(ser == OBD_SYMBOL_SER, "invalid asset bits"); - sym.asset_num = HIVE_ASSET_NUM_HBD; - break; - case VESTS_SYMBOL_SER & 0xFFFFFFFF: - s.read(((char *)&ser) + 4, 4); - FC_ASSERT(ser == VESTS_SYMBOL_SER, "invalid asset bits"); - sym.asset_num = HIVE_ASSET_NUM_VESTS; - break; - default: - sym.asset_num = uint32_t(ser); - } - sym.validate(); -} - -} // namespace raw - -inline void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &var, uint32_t max_depth) { - try { - mutable_variant_object o; - o(ASSET_SYMBOL_NAI_KEY, sym.to_nai_string())(ASSET_SYMBOL_DECIMALS_KEY, sym.decimals()); - var = std::move(o); - } - FC_CAPTURE_AND_RETHROW() -} - -inline void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t max_depth) { - using graphene::peerplays_sidechain::hive::asset_symbol_type; - - try { - FC_ASSERT(var.is_object(), "Asset symbol is expected to be an object."); - - auto &o = var.get_object(); - - auto nai = o.find(ASSET_SYMBOL_NAI_KEY); - FC_ASSERT(nai != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); - FC_ASSERT(nai->value().is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY)); - - auto decimals = o.find(ASSET_SYMBOL_DECIMALS_KEY); - FC_ASSERT(decimals != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); - FC_ASSERT(decimals->value().is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY)); - FC_ASSERT(decimals->value().as_uint64() <= HIVE_ASSET_MAX_DECIMALS, - "Expected decimals to be less than or equal to ${num}", ("num", HIVE_ASSET_MAX_DECIMALS)); - - sym = asset_symbol_type::from_nai_string(nai->value().as_string().c_str(), decimals->value().as(max_depth)); - } - FC_CAPTURE_AND_RETHROW() -} - -} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index e669491a..70a199be 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -477,19 +478,19 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob //===== - uint32_t asset_num = 0; + uint64_t symbol = 0; if (swwo.withdraw_currency == "HBD") { - asset_num = HIVE_ASSET_NUM_HBD; + symbol = TBD_SYMBOL_SER; } if (swwo.withdraw_currency == "HIVE") { - asset_num = HIVE_ASSET_NUM_HIVE; + symbol = TESTS_SYMBOL_SER; } hive::transfer_operation t_op; t_op.from = "son-account"; t_op.to = swwo.withdraw_address; t_op.amount.amount = swwo.withdraw_amount; - t_op.amount.symbol = hive::asset_symbol_type::from_asset_num(asset_num); + t_op.amount.symbol = symbol; t_op.memo = ""; std::string block_id_str = node_rpc_client->get_head_block_id(); @@ -707,42 +708,6 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { } } } - - //========== - { - hive::transfer_operation t_op; - t_op.from = "sonaccount01"; - t_op.to = "account05"; - t_op.amount.amount = 1000; - t_op.amount.symbol = hive::asset_symbol_type::from_asset_num(HIVE_ASSET_NUM_HIVE); - t_op.memo = ""; - - std::string block_id_str = node_rpc_client->get_head_block_id(); - hive::block_id_type head_block_id(block_id_str); - //hive::block_id_type head_block_id("000087723a5513e7cc0f03a71bf05a5b7b36102f"); - - std::string head_block_time_str = node_rpc_client->get_head_block_time(); - time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str); - //time_point head_block_time = fc::time_point_sec::from_iso_string("2021-04-23T10:38:03"); - - hive::signed_transaction htrx; - htrx.set_reference_block(head_block_id); - htrx.set_expiration(head_block_time + fc::seconds(30)); - - htrx.operations.push_back(t_op); - ilog("TRX: ${htrx}", ("htrx", htrx)); - - std::string chain_id_str = node_rpc_client->get_chain_id(); - const hive::chain_id_type chain_id(chain_id_str); - - fc::optional privkey = graphene::utilities::wif_to_key(get_private_key("sonaccount01")); - htrx.sign(*privkey, chain_id); - - std::string params = fc::json::to_string(htrx); - ilog("HTRX: ${htrx}", ("htrx", params)); - node_rpc_client->network_broadcast_api_broadcast_transaction(params); - } - //========== } }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 33f869b1..ff876b0c 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -12,9 +12,9 @@ sidechain_net_manager::sidechain_net_manager(peerplays_sidechain_plugin &_plugin plugin(_plugin), database(_plugin.database()) { - database.applied_block.connect([&](const signed_block &b) { - on_applied_block(b); - }); + //database.applied_block.connect([&](const signed_block &b) { + // on_applied_block(b); + //}); } sidechain_net_manager::~sidechain_net_manager() { -- 2.45.2 From 189229b20e2f2b61b1dd8b6b43f4bbdcba3c3a4b Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 25 May 2021 13:28:28 +0200 Subject: [PATCH 17/57] Hive network recognition and proper asset encoding --- .../peerplays_sidechain/hive/asset.cpp | 32 ++++++- .../peerplays_sidechain/hive/asset.hpp | 2 + .../peerplays_sidechain/hive/types.hpp | 5 ++ .../peerplays_sidechain/hive/types_fwd.hpp | 90 ------------------- .../sidechain_net_handler_hive.hpp | 3 + .../sidechain_net_handler_hive.cpp | 24 ++++- 6 files changed, 61 insertions(+), 95 deletions(-) delete mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp diff --git a/libraries/plugins/peerplays_sidechain/hive/asset.cpp b/libraries/plugins/peerplays_sidechain/hive/asset.cpp index 9adefe94..7417107f 100644 --- a/libraries/plugins/peerplays_sidechain/hive/asset.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/asset.cpp @@ -9,12 +9,33 @@ #define ASSET_PRECISION_KEY "precision" #define ASSET_NAI_KEY "nai" +namespace graphene { namespace peerplays_sidechain { namespace hive { + +uint64_t asset::hbd_symbol_ser = HBD_SYMBOL_SER; +uint64_t asset::hive_symbol_ser = HIVE_SYMBOL_SER; + +}}} // namespace graphene::peerplays_sidechain::hive + namespace fc { void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth) { try { - variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(TESTS_PRECISION))(ASSET_NAI_KEY, TESTS_NAI); - vo = v; + if (var.symbol == HBD_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(HBD_PRECISION))(ASSET_NAI_KEY, HBD_NAI); + vo = v; + } + if (var.symbol == HIVE_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(HIVE_PRECISION))(ASSET_NAI_KEY, HIVE_NAI); + vo = v; + } + if (var.symbol == TBD_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(TBD_PRECISION))(ASSET_NAI_KEY, TBD_NAI); + vo = v; + } + if (var.symbol == TESTS_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(TESTS_PRECISION))(ASSET_NAI_KEY, TESTS_NAI); + vo = v; + } } FC_CAPTURE_AND_RETHROW() } @@ -36,7 +57,12 @@ void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::a FC_ASSERT(v_object.contains(ASSET_NAI_KEY), "NAI field doesn't exist."); FC_ASSERT(v_object[ASSET_NAI_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_NAI_KEY)); - vo.symbol = TESTS_SYMBOL_SER; + if (v_object[ASSET_NAI_KEY].as(max_depth) == HBD_NAI) { + vo.symbol = graphene::peerplays_sidechain::hive::asset::hbd_symbol_ser; + } + if (v_object[ASSET_NAI_KEY].as(max_depth) == HIVE_NAI) { + vo.symbol = graphene::peerplays_sidechain::hive::asset::hive_symbol_ser; + } } FC_CAPTURE_AND_RETHROW() } diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp index 8b526e35..d79d2e7d 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp @@ -25,6 +25,8 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { #define TESTS_SYMBOL_SER (uint64_t(3) | (TESTS_SYMBOL_U64 << 8)) struct asset { + static uint64_t hbd_symbol_ser; + static uint64_t hive_symbol_ser; share_type amount; uint64_t symbol; }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp index 724373e5..85e16a8c 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -5,6 +5,11 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { +enum network { + mainnet, + testnet +}; + struct void_t {}; typedef fc::static_variant future_extensions; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp deleted file mode 100644 index 7276f297..00000000 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types_fwd.hpp +++ /dev/null @@ -1,90 +0,0 @@ -//#pragma once -//#include -//#include -//#include -// -//#include "asset_symbol.hpp" -// -//namespace fc { -//class variant; -//} // namespace fc -// -//namespace graphene { namespace peerplays_sidechain { namespace hive { -////template< typename Storage = fc::uint128 > -////class fixed_string_impl; -// -//class asset_symbol_type; -////class legacy_hive_asset_symbol_type; -////struct legacy_hive_asset; -//}}} // namespace graphene::peerplays_sidechain::hive -// -////using boost::container::flat_set; -//// -////template< class Key > -////class flat_set_ex: public flat_set< Key > -////{ -//// public: -//// -//// flat_set_ex& operator=( const flat_set< Key >& obj ) -//// { -//// flat_set< Key >::operator=( obj ); -//// return *this; -//// } -//// -//// flat_set_ex& operator=( const flat_set_ex& obj ) -//// { -//// flat_set< Key >::operator=( obj ); -//// return *this; -//// } -////}; -// -//namespace fc { -//namespace raw { -// -////template -////void pack( Stream& s, const flat_set_ex& value ); -////template -////void unpack( Stream& s, flat_set_ex& value, uint32_t depth = 0 ); -// -////template< typename Stream, typename Storage > -////inline void pack( Stream& s, const hive::protocol::fixed_string_impl< Storage >& u ); -////template< typename Stream, typename Storage > -////inline void unpack( Stream& s, hive::protocol::fixed_string_impl< Storage >& u, uint32_t depth = 0 ); -// -//template -//inline void pack(Stream &s, const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t depth = 0); -//template -//inline void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t depth = 0); -// -////template< typename Stream > -////inline void pack( Stream& s, const hive::protocol::legacy_hive_asset_symbol_type& sym ); -////template< typename Stream > -////inline void unpack( Stream& s, hive::protocol::legacy_hive_asset_symbol_type& sym, uint32_t depth = 0 ); -// -//} // namespace raw -// -////template -////void to_variant( const flat_set_ex& var, variant& vo ); -// -////template -////void from_variant( const variant& var, flat_set_ex& vo ); -// -////template< typename Storage > -////inline void to_variant( const hive::protocol::fixed_string_impl< Storage >& s, fc::variant& v ); -////template< typename Storage > -////inline void from_variant( const variant& v, hive::protocol::fixed_string_impl< Storage >& s ); -// -//inline void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &v, uint32_t max_depth); -// -////inline void from_variant( const fc::variant& v, hive::protocol::legacy_hive_asset& leg ); -////inline void to_variant( const hive::protocol::legacy_hive_asset& leg, fc::variant& v ); -// -////template struct get_typename> -////{ -//// static const char* name() { -//// static std::string n = std::string("flat_set<") + get_typename< fc::flat_set >::name() + ">"; -//// return n.c_str(); -//// } -////}; -// -//} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index e1050158..0b5494d2 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -18,6 +18,7 @@ public: std::string account_history_api_get_transaction(std::string transaction_id); std::string block_api_get_block(uint32_t block_number); + std::string condenser_api_get_config(); std::string condenser_api_get_transaction(std::string transaction_id); std::string database_api_get_dynamic_global_properties(); std::string database_api_get_version(); @@ -26,6 +27,7 @@ public: std::string get_chain_id(); std::string get_head_block_id(); std::string get_head_block_time(); + std::string get_is_test_net(); }; class hive_wallet_rpc_client : public rpc_client { @@ -71,6 +73,7 @@ private: hive_wallet_rpc_client *wallet_rpc_client; hive::chain_id_type chain_id; + hive::network network_type; uint64_t last_block_received; fc::future _listener_task; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 70a199be..be7acfd3 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -42,6 +42,11 @@ std::string hive_node_rpc_client::block_api_get_block(uint32_t block_number) { return send_post_request("block_api.get_block", params, false); } +std::string hive_node_rpc_client::condenser_api_get_config() { + std::string params = "[]"; + return send_post_request("condenser_api.get_config", params, false); +} + std::string hive_node_rpc_client::condenser_api_get_transaction(std::string transaction_id) { std::string params = "[\"" + transaction_id + "\"]"; return send_post_request("condenser_api.get_transaction", params, false); @@ -75,6 +80,11 @@ std::string hive_node_rpc_client::get_head_block_time() { return retrieve_value_from_reply(reply_str, "time"); } +std::string hive_node_rpc_client::get_is_test_net() { + std::string reply_str = condenser_api_get_config(); + return retrieve_value_from_reply(reply_str, "IS_TEST_NET"); +} + hive_wallet_rpc_client::hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : rpc_client(_ip, _port, _user, _password) { } @@ -182,6 +192,16 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi std::string chain_id_str = node_rpc_client->get_chain_id(); chain_id = chain_id_type(chain_id_str); + std::string is_test_net = node_rpc_client->get_is_test_net(); + network_type = is_test_net.compare("true") == 0 ? hive::network::testnet : hive::network::mainnet; + if (network_type == hive::network::mainnet) { + hive::asset::hbd_symbol_ser = HBD_SYMBOL_SER; + hive::asset::hive_symbol_ser = HIVE_SYMBOL_SER; + } else { + hive::asset::hbd_symbol_ser = TBD_SYMBOL_SER; + hive::asset::hive_symbol_ser = TESTS_SYMBOL_SER; + } + last_block_received = 0; schedule_hive_listener(); event_received.connect([this](const std::string &event_data) { @@ -480,10 +500,10 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob uint64_t symbol = 0; if (swwo.withdraw_currency == "HBD") { - symbol = TBD_SYMBOL_SER; + symbol = hive::asset::hbd_symbol_ser; } if (swwo.withdraw_currency == "HIVE") { - symbol = TESTS_SYMBOL_SER; + symbol = hive::asset::hive_symbol_ser; } hive::transfer_operation t_op; -- 2.45.2 From 851ac2792da9255009cadce76f98dc622e5909ed Mon Sep 17 00:00:00 2001 From: serkixenos Date: Sat, 29 May 2021 02:25:57 +0200 Subject: [PATCH 18/57] son_wallet_update_operation proposal approval for Hive --- .../sidechain_net_handler_hive.hpp | 4 + .../sidechain_net_handler_hive.cpp | 95 ++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 0b5494d2..b99b3c22 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -75,6 +75,10 @@ private: hive::chain_id_type chain_id; hive::network network_type; + std::string create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address); + std::string create_deposit_transaction(const son_wallet_deposit_object &swdo); + std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); + uint64_t last_block_received; fc::future _listener_task; fc::signal event_received; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index be7acfd3..42f89ceb 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -218,7 +218,7 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { bool should_approve = false; - //const chain::global_property_object &gpo = database.get_global_properties(); + const chain::global_property_object &gpo = database.get_global_properties(); int32_t op_idx_0 = -1; chain::operation op_obj_idx_0; @@ -228,10 +228,101 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { op_obj_idx_0 = po.proposed_transaction.operations[0]; } + int32_t op_idx_1 = -1; + chain::operation op_obj_idx_1; + (void)op_idx_1; + + if (po.proposed_transaction.operations.size() >= 2) { + op_idx_1 = po.proposed_transaction.operations[1].which(); + op_obj_idx_1 = po.proposed_transaction.operations[1]; + } + switch (op_idx_0) { case chain::operation::tag::value: { - should_approve = true; + bool address_ok = false; + bool transaction_ok = false; + son_wallet_id_type swo_id = op_obj_idx_0.get().son_wallet_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swo = idx.find(swo_id); + if (swo != idx.end()) { + + auto active_sons = gpo.active_sons; + vector wallet_sons = swo->sons; + + bool son_sets_equal = (active_sons.size() == wallet_sons.size()); + + if (son_sets_equal) { + for (size_t i = 0; i < active_sons.size(); i++) { + son_sets_equal = son_sets_equal && active_sons.at(i) == wallet_sons.at(i); + } + } + + if (son_sets_equal) { + address_ok = (op_obj_idx_0.get().address == "son-account"); + } + + if (po.proposed_transaction.operations.size() >= 2) { + object_id_type object_id = op_obj_idx_1.get().object_id; + std::string op_tx_str = op_obj_idx_1.get().transaction; + + const auto &st_idx = database.get_index_type().indices().get(); + const auto st = st_idx.find(object_id); + if (st == st_idx.end()) { + + std::string tx_str = ""; + + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swo = idx.find(object_id); + if (swo != idx.end()) { + + std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str)); + hive::signed_transaction op_trx; + fc::raw::unpack(ss_trx, op_trx, 1000); + ilog("TRX: ${op_trx}", ("op_trx", op_trx)); + + fc::flat_map account_auths; + uint32_t total_weight = 0; + for (const auto &wallet_son : wallet_sons) { + total_weight = total_weight + wallet_son.weight; + account_auths[wallet_son.sidechain_public_keys.at(sidechain)] = wallet_son.weight; + } + + std::string memo_key = wallet_rpc_client->get_account_memo_key("son-account"); + + hive::authority active; + active.weight_threshold = total_weight * 2 / 3 + 1; + active.account_auths = account_auths; + + hive::account_update_operation auo; + auo.account = "son-account"; + auo.active = active; + auo.memo_key = op_trx.operations[0].get().memo_key; + + hive::signed_transaction htrx; + htrx.ref_block_num = op_trx.ref_block_num; + htrx.ref_block_prefix = op_trx.ref_block_prefix; + htrx.set_expiration(op_trx.expiration); + + htrx.operations.push_back(auo); + ilog("TRX: ${htrx}", ("htrx", htrx)); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + tx_str = boost::algorithm::hex(ss.str()); + } + } + + transaction_ok = (op_tx_str == tx_str); + } + } else { + transaction_ok = true; + } + } + + should_approve = address_ok && + transaction_ok; break; } -- 2.45.2 From 6faec4901a1a5645c7e40db9d7c5d76a0bb59c76 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 7 Jun 2021 13:35:02 +0200 Subject: [PATCH 19/57] Deposit/Withdraw process operation proposal approval for Hive --- .../sidechain_net_handler_hive.cpp | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 42f89ceb..ebd021ca 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -383,7 +383,88 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { } case chain::operation::tag::value: { - should_approve = true; + bool process_ok = false; + bool transaction_ok = false; + son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get().son_wallet_withdraw_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(swwo_id); + if (swwo != idx.end()) { + + uint32_t swwo_block_num = swwo->block_num; + std::string swwo_peerplays_transaction_id = swwo->peerplays_transaction_id; + uint32_t swwo_op_idx = std::stoll(swwo->peerplays_uid.substr(swwo->peerplays_uid.find_last_of("-") + 1)); + + const auto &block = database.fetch_block_by_number(swwo_block_num); + + for (const auto &tx : block->transactions) { + if (tx.id().str() == swwo_peerplays_transaction_id) { + operation op = tx.operations[swwo_op_idx]; + transfer_operation t_op = op.get(); + + price asset_price = database.get(t_op.amount.asset_id).options.core_exchange_rate; + asset peerplays_asset = asset(t_op.amount.amount * asset_price.base.amount / asset_price.quote.amount); + + process_ok = (t_op.to == gpo.parameters.son_account()) && + (swwo->peerplays_from == t_op.from) && + (swwo->peerplays_asset == peerplays_asset); + break; + } + } + + object_id_type object_id = op_obj_idx_1.get().object_id; + std::string op_tx_str = op_obj_idx_1.get().transaction; + + const auto &st_idx = database.get_index_type().indices().get(); + const auto st = st_idx.find(object_id); + if (st == st_idx.end()) { + + std::string tx_str = ""; + + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(object_id); + if (swwo != idx.end()) { + + std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str)); + hive::signed_transaction op_trx; + fc::raw::unpack(ss_trx, op_trx, 1000); + ilog("TRX: ${op_trx}", ("op_trx", op_trx)); + + uint64_t symbol = 0; + if (swwo->withdraw_currency == "HBD") { + symbol = hive::asset::hbd_symbol_ser; + } + if (swwo->withdraw_currency == "HIVE") { + symbol = hive::asset::hive_symbol_ser; + } + + hive::transfer_operation t_op; + t_op.from = "son-account"; + t_op.to = swwo->withdraw_address; + t_op.amount.amount = swwo->withdraw_amount; + t_op.amount.symbol = symbol; + t_op.memo = ""; + + hive::signed_transaction htrx; + htrx.ref_block_num = op_trx.ref_block_num; + htrx.ref_block_prefix = op_trx.ref_block_prefix; + htrx.set_expiration(op_trx.expiration); + + htrx.operations.push_back(t_op); + ilog("TRX: ${htrx}", ("htrx", htrx)); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + tx_str = boost::algorithm::hex(ss.str()); + } + } + + transaction_ok = (op_tx_str == tx_str); + } + } + + should_approve = process_ok && + transaction_ok; break; } -- 2.45.2 From 3b25ec29eb8f34c311818a523fb29d5371e0b0e1 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 8 Jun 2021 17:00:35 +0200 Subject: [PATCH 20/57] sidechain_transaction_sign_operation proposal approval for Hive --- .../sidechain_net_handler_hive.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index ebd021ca..b3c4bf50 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -470,6 +470,23 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { case chain::operation::tag::value: { should_approve = true; + son_id_type signer = op_obj_idx_0.get().signer; + std::string signature = op_obj_idx_0.get().signature; + sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get().sidechain_transaction_id; + const auto &st_idx = database.get_index_type().indices().get(); + const auto sto = st_idx.find(sidechain_transaction_id); + if (sto == st_idx.end()) { + should_approve = false; + break; + } + + const auto &s_idx = database.get_index_type().indices().get(); + const auto son = s_idx.find(signer); + if (son == s_idx.end()) { + should_approve = false; + break; + } + break; } -- 2.45.2 From ca1e68c13f9ea1bbdb3e23bd66616ba664489cb2 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 28 Jun 2021 15:51:40 +0200 Subject: [PATCH 21/57] sidechain_transaction_settle_operation proposal approval for Hive --- bkup_CMakeCache.txt | 794 ------------------ .../sidechain_net_handler.hpp | 2 +- .../sidechain_net_handler_bitcoin.hpp | 2 +- .../sidechain_net_handler_hive.hpp | 4 +- .../sidechain_net_handler_peerplays.hpp | 2 +- .../sidechain_net_handler.cpp | 11 +- .../sidechain_net_handler_bitcoin.cpp | 19 +- .../sidechain_net_handler_hive.cpp | 58 +- .../sidechain_net_handler_peerplays.cpp | 32 +- 9 files changed, 92 insertions(+), 832 deletions(-) delete mode 100644 bkup_CMakeCache.txt diff --git a/bkup_CMakeCache.txt b/bkup_CMakeCache.txt deleted file mode 100644 index daa267e9..00000000 --- a/bkup_CMakeCache.txt +++ /dev/null @@ -1,794 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /home/pbattu/git/18.04/peerplays -# It was generated by CMake: /usr/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -BOOST_ROOT:PATH=/home/pbattu/git/18.04/boost_1_67_0 - -//The threading library used by boost-thread -BOOST_THREAD_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpthread.so - -//Build bitshares executables (witness node, cli wallet, etc) -BUILD_BITSHARES_PROGRAMS:BOOL=TRUE - -//Build bitshares unit tests -BUILD_BITSHARES_TESTS:BOOL=TRUE - -//Build websocketpp examples. -BUILD_EXAMPLES:BOOL=OFF - -//Build websocketpp tests. -BUILD_TESTS:BOOL=OFF - -//Value Computed by CMake -BitShares_BINARY_DIR:STATIC=/home/pbattu/git/18.04/peerplays - -//Value Computed by CMake -BitShares_SOURCE_DIR:STATIC=/home/pbattu/git/18.04/peerplays - -//Boost chrono library (debug) -Boost_CHRONO_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_chrono.a - -//Boost chrono library (release) -Boost_CHRONO_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_chrono.a - -//Boost context library (debug) -Boost_CONTEXT_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_context.a - -//Boost context library (release) -Boost_CONTEXT_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_context.a - -//Boost coroutine library (debug) -Boost_COROUTINE_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_coroutine.a - -//Boost coroutine library (release) -Boost_COROUTINE_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_coroutine.a - -//Boost date_time library (debug) -Boost_DATE_TIME_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_date_time.a - -//Boost date_time library (release) -Boost_DATE_TIME_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_date_time.a - -//The directory containing a CMake configuration file for Boost. -Boost_DIR:PATH=Boost_DIR-NOTFOUND - -//Boost filesystem library (debug) -Boost_FILESYSTEM_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_filesystem.a - -//Boost filesystem library (release) -Boost_FILESYSTEM_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_filesystem.a - -//Path to a file. -Boost_INCLUDE_DIR:PATH=/home/pbattu/git/18.04/boost_1_67_0/include - -//Boost iostreams library (debug) -Boost_IOSTREAMS_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_iostreams.a - -//Boost iostreams library (release) -Boost_IOSTREAMS_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_iostreams.a - -//Boost library directory -Boost_LIBRARY_DIR:PATH=/home/pbattu/git/18.04/boost_1_67_0/lib - -//Boost library directory DEBUG -Boost_LIBRARY_DIR_DEBUG:PATH=/home/pbattu/git/18.04/boost_1_67_0/lib - -//Boost library directory RELEASE -Boost_LIBRARY_DIR_RELEASE:PATH=/home/pbattu/git/18.04/boost_1_67_0/lib - -//Boost locale library (debug) -Boost_LOCALE_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_locale.a - -//Boost locale library (release) -Boost_LOCALE_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_locale.a - -//Boost program_options library (debug) -Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_program_options.a - -//Boost program_options library (release) -Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_program_options.a - -//Boost serialization library (debug) -Boost_SERIALIZATION_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_serialization.a - -//Boost serialization library (release) -Boost_SERIALIZATION_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_serialization.a - -//Boost signals library (debug) -Boost_SIGNALS_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_signals.a - -//Boost signals library (release) -Boost_SIGNALS_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_signals.a - -//Boost system library (debug) -Boost_SYSTEM_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_system.a - -//Boost system library (release) -Boost_SYSTEM_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_system.a - -//Boost thread library (debug) -Boost_THREAD_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_thread.a - -//Boost thread library (release) -Boost_THREAD_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_thread.a - -//Boost unit_test_framework library (debug) -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_unit_test_framework.a - -//Boost unit_test_framework library (release) -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_unit_test_framework.a - -//ON or OFF -Boost_USE_STATIC_LIBS:STRING=ON - -//Path to a program. -CMAKE_AR:FILEPATH=/usr/bin/ar - -//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or -// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. -CMAKE_BUILD_TYPE:STRING=Debug - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//Configurations -CMAKE_CONFIGURATION_TYPES:STRING=Release;RelWithDebInfo;Debug - -//CXX compiler -CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-5 - -//A wrapper around 'ar' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-5 - -//A wrapper around 'ranlib' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-5 - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//C compiler -CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-5 - -//A wrapper around 'ar' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-5 - -//A wrapper around 'ranlib' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-5 - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Enable/Disable output of compile commands during generation. -CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//Path to a program. -CMAKE_LINKER:FILEPATH=/usr/bin/ld - -//Path to a program. -CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/usr/bin/nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=BitShares - -//Path to a program. -CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_STRIP:FILEPATH=/usr/bin/strip - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Path to a library. -CURSES_CURSES_LIBRARY:FILEPATH=CURSES_CURSES_LIBRARY-NOTFOUND - -//Path to a library. -CURSES_FORM_LIBRARY:FILEPATH=CURSES_FORM_LIBRARY-NOTFOUND - -//Path to a file. -CURSES_INCLUDE_PATH:PATH=CURSES_INCLUDE_PATH-NOTFOUND - -//Path to a library. -CURSES_NCURSES_LIBRARY:FILEPATH=CURSES_NCURSES_LIBRARY-NOTFOUND - -//Dot tool for use with Doxygen -DOXYGEN_DOT_EXECUTABLE:FILEPATH=DOXYGEN_DOT_EXECUTABLE-NOTFOUND - -//Doxygen documentation generation tool (http://www.doxygen.org) -DOXYGEN_EXECUTABLE:FILEPATH=DOXYGEN_EXECUTABLE-NOTFOUND - -//secp256k1 or openssl or mixed -ECC_IMPL:STRING=secp256k1 - -//Build BitShares for code coverage analysis -ENABLE_COVERAGE_TESTING:BOOL=FALSE - -//Build websocketpp with CPP11 features enabled. -ENABLE_CPP11:BOOL=ON - -//TRUE to try to use full zlib for compression, FALSE to use miniz.c -FC_USE_FULL_ZLIB:BOOL=FALSE - -//Git command line client -GIT_EXECUTABLE:FILEPATH=/usr/bin/git - -//location of the genesis.json to embed in the executable -GRAPHENE_EGENESIS_JSON:PATH=/home/pbattu/git/18.04/peerplays/genesis.json - -//The directory containing a CMake configuration file for Gperftools. -Gperftools_DIR:PATH=Gperftools_DIR-NOTFOUND - -//Installation directory for CMake files -INSTALL_CMAKE_DIR:PATH=lib/cmake/websocketpp - -//Installation directory for header files -INSTALL_INCLUDE_DIR:PATH=include - -//Log long API calls over websocket (ON OR OFF) -LOG_LONG_API:BOOL=ON - -//Max API execution time in ms -LOG_LONG_API_MAX_MS:STRING=1000 - -//API execution time in ms at which to warn -LOG_LONG_API_WARN_MS:STRING=750 - -//Path to a library. -OPENSSL_CRYPTO_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libcrypto.a - -//Path to a file. -OPENSSL_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -OPENSSL_SSL_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libssl.a - -//Path to a program. -PERL_EXECUTABLE:FILEPATH=/usr/bin/perl - -//pkg-config executable -PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config - -//Path to a file. -READLINE_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -READLINE_LIBRARIES:FILEPATH=/usr/lib/x86_64-linux-gnu/libreadline.so - -//Path to a file. -Readline_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -Readline_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libreadline.so - -//Path to a file. -Readline_ROOT_DIR:PATH=/usr - -//OFF -UNITY_BUILD:BOOL=OFF - -//Path to a file. -ZLIB_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -ZLIB_LIBRARY_DEBUG:FILEPATH=ZLIB_LIBRARY_DEBUG-NOTFOUND - -//Path to a library. -ZLIB_LIBRARY_RELEASE:FILEPATH=/usr/lib/x86_64-linux-gnu/libz.so - -//Value Computed by CMake -fc_BINARY_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc - -//Dependencies for the target -fc_LIB_DEPENDS:STATIC=general;-L/usr/local/lib;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_thread.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_date_time.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_filesystem.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_system.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_program_options.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_signals.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_serialization.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_chrono.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_unit_test_framework.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_context.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_locale.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_iostreams.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_coroutine.a;general;/usr/lib/x86_64-linux-gnu/libpthread.so;general;/usr/lib/x86_64-linux-gnu/libssl.a;general;/usr/lib/x86_64-linux-gnu/libcrypto.a;general;/usr/lib/x86_64-linux-gnu/libz.so;general;dl;general;rt;general;/usr/lib/x86_64-linux-gnu/libreadline.so;general;secp256k1; - -//Value Computed by CMake -fc_SOURCE_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc - -//Dependencies for the target -graphene_account_history_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_accounts_list_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_affiliate_stats_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_app_LIB_DEPENDS:STATIC=general;graphene_market_history;general;graphene_account_history;general;graphene_accounts_list;general;graphene_affiliate_stats;general;graphene_chain;general;fc;general;graphene_db;general;graphene_net;general;graphene_time;general;graphene_utilities;general;graphene_debug_witness;general;graphene_bookie; - -//Dependencies for the target -graphene_bookie_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_chain_LIB_DEPENDS:STATIC=general;fc;general;graphene_db; - -//Dependencies for the target -graphene_db_LIB_DEPENDS:STATIC=general;fc; - -//Dependencies for the target -graphene_debug_witness_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_delayed_node_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_egenesis_brief_LIB_DEPENDS:STATIC=general;graphene_chain;general;fc; - -//Dependencies for the target -graphene_egenesis_full_LIB_DEPENDS:STATIC=general;graphene_chain;general;fc; - -//Dependencies for the target -graphene_egenesis_none_LIB_DEPENDS:STATIC=general;graphene_chain;general;fc; - -//Dependencies for the target -graphene_generate_genesis_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app;general;graphene_time; - -//Dependencies for the target -graphene_generate_uia_sharedrop_genesis_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app;general;graphene_time; - -//Dependencies for the target -graphene_market_history_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_net_LIB_DEPENDS:STATIC=general;fc;general;graphene_db; - -//Dependencies for the target -graphene_snapshot_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_time_LIB_DEPENDS:STATIC=general;fc; - -//Dependencies for the target -graphene_utilities_LIB_DEPENDS:STATIC=general;fc; - -//Dependencies for the target -graphene_wallet_LIB_DEPENDS:STATIC=general;graphene_app;general;graphene_net;general;graphene_chain;general;graphene_utilities;general;fc;general;dl; - -//Dependencies for the target -graphene_witness_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Value Computed by CMake -websocketpp_BINARY_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc/vendor/websocketpp - -//Value Computed by CMake -websocketpp_SOURCE_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc/vendor/websocketpp - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: BOOST_ROOT -BOOST_ROOT-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CHRONO_LIBRARY_DEBUG -Boost_CHRONO_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CHRONO_LIBRARY_RELEASE -Boost_CHRONO_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CONTEXT_LIBRARY_DEBUG -Boost_CONTEXT_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CONTEXT_LIBRARY_RELEASE -Boost_CONTEXT_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_COROUTINE_LIBRARY_DEBUG -Boost_COROUTINE_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_COROUTINE_LIBRARY_RELEASE -Boost_COROUTINE_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_DATE_TIME_LIBRARY_DEBUG -Boost_DATE_TIME_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_DATE_TIME_LIBRARY_RELEASE -Boost_DATE_TIME_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_DIR -Boost_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_FILESYSTEM_LIBRARY_DEBUG -Boost_FILESYSTEM_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_FILESYSTEM_LIBRARY_RELEASE -Boost_FILESYSTEM_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_INCLUDE_DIR -Boost_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_IOSTREAMS_LIBRARY_DEBUG -Boost_IOSTREAMS_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_IOSTREAMS_LIBRARY_RELEASE -Boost_IOSTREAMS_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LIBRARY_DIR -Boost_LIBRARY_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LIBRARY_DIR_DEBUG -Boost_LIBRARY_DIR_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LIBRARY_DIR_RELEASE -Boost_LIBRARY_DIR_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LOCALE_LIBRARY_DEBUG -Boost_LOCALE_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LOCALE_LIBRARY_RELEASE -Boost_LOCALE_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG -Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE -Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SERIALIZATION_LIBRARY_DEBUG -Boost_SERIALIZATION_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SERIALIZATION_LIBRARY_RELEASE -Boost_SERIALIZATION_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SIGNALS_LIBRARY_DEBUG -Boost_SIGNALS_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SIGNALS_LIBRARY_RELEASE -Boost_SIGNALS_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SYSTEM_LIBRARY_DEBUG -Boost_SYSTEM_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SYSTEM_LIBRARY_RELEASE -Boost_SYSTEM_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_THREAD_LIBRARY_DEBUG -Boost_THREAD_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_THREAD_LIBRARY_RELEASE -Boost_THREAD_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/home/pbattu/git/18.04/peerplays -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=10 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 -//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE -CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/usr/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER -CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR -CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB -CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER -CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_AR -CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB -CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS -CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Unix Makefiles -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Have symbol pthread_create -CMAKE_HAVE_LIBC_CREATE:INTERNAL= -//Have library pthreads -CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= -//Have library pthread -CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 -//Have include pthread.h -CMAKE_HAVE_PTHREAD_H:INTERNAL=1 -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/home/pbattu/git/18.04/peerplays -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=37 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.10 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//uname command -CMAKE_UNAME:INTERNAL=/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_CURSES_LIBRARY -CURSES_CURSES_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_FORM_LIBRARY -CURSES_FORM_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_INCLUDE_PATH -CURSES_INCLUDE_PATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_NCURSES_LIBRARY -CURSES_NCURSES_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: DOXYGEN_DOT_EXECUTABLE -DOXYGEN_DOT_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: DOXYGEN_EXECUTABLE -DOXYGEN_EXECUTABLE-ADVANCED:INTERNAL=1 -//Details about finding OpenSSL -FIND_PACKAGE_MESSAGE_DETAILS_OpenSSL:INTERNAL=[/usr/lib/x86_64-linux-gnu/libcrypto.a][/usr/include][v1.1.0g()] -//Details about finding Perl -FIND_PACKAGE_MESSAGE_DETAILS_Perl:INTERNAL=[/usr/bin/perl][v5.26.1()] -//Details about finding Readline -FIND_PACKAGE_MESSAGE_DETAILS_Readline:INTERNAL=[/usr/include][/usr/lib/x86_64-linux-gnu/libreadline.so][v()] -//Details about finding Threads -FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] -//Details about finding ZLIB -FIND_PACKAGE_MESSAGE_DETAILS_ZLIB:INTERNAL=[/usr/lib/x86_64-linux-gnu/libz.so][/usr/include][v1.2.11()] -//ADVANCED property for variable: GIT_EXECUTABLE -GIT_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENSSL_CRYPTO_LIBRARY -OPENSSL_CRYPTO_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENSSL_INCLUDE_DIR -OPENSSL_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENSSL_SSL_LIBRARY -OPENSSL_SSL_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PERL_EXECUTABLE -PERL_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE -PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Readline_INCLUDE_DIR -Readline_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Readline_LIBRARY -Readline_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Readline_ROOT_DIR -Readline_ROOT_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_INCLUDE_DIR -ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_DEBUG -ZLIB_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_RELEASE -ZLIB_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//Last used BOOST_ROOT value. -_BOOST_ROOT_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0 -//Components requested for this build tree. -_Boost_COMPONENTS_SEARCHED:INTERNAL=chrono;context;coroutine;date_time;filesystem;iostreams;locale;program_options;serialization;signals;system;thread;unit_test_framework -//Last used Boost_INCLUDE_DIR value. -_Boost_INCLUDE_DIR_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/include -//Last used Boost_LIBRARY_DIR_DEBUG value. -_Boost_LIBRARY_DIR_DEBUG_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/lib -//Last used Boost_LIBRARY_DIR value. -_Boost_LIBRARY_DIR_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/lib -//Last used Boost_LIBRARY_DIR_RELEASE value. -_Boost_LIBRARY_DIR_RELEASE_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/lib -//Last used Boost_NAMESPACE value. -_Boost_NAMESPACE_LAST:INTERNAL=boost -//Last used Boost_USE_MULTITHREADED value. -_Boost_USE_MULTITHREADED_LAST:INTERNAL=TRUE -//Last used Boost_USE_STATIC_LIBS value. -_Boost_USE_STATIC_LIBS_LAST:INTERNAL=ON -_OPENSSL_CFLAGS:INTERNAL= -_OPENSSL_CFLAGS_I:INTERNAL= -_OPENSSL_CFLAGS_OTHER:INTERNAL= -_OPENSSL_FOUND:INTERNAL=1 -_OPENSSL_INCLUDEDIR:INTERNAL=/usr/include -_OPENSSL_INCLUDE_DIRS:INTERNAL= -_OPENSSL_LDFLAGS:INTERNAL=-lssl;-lcrypto -_OPENSSL_LDFLAGS_OTHER:INTERNAL= -_OPENSSL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu -_OPENSSL_LIBRARIES:INTERNAL=ssl;crypto -_OPENSSL_LIBRARY_DIRS:INTERNAL= -_OPENSSL_LIBS:INTERNAL= -_OPENSSL_LIBS_L:INTERNAL= -_OPENSSL_LIBS_OTHER:INTERNAL= -_OPENSSL_LIBS_PATHS:INTERNAL= -_OPENSSL_PREFIX:INTERNAL=/usr -_OPENSSL_STATIC_CFLAGS:INTERNAL= -_OPENSSL_STATIC_CFLAGS_I:INTERNAL= -_OPENSSL_STATIC_CFLAGS_OTHER:INTERNAL= -_OPENSSL_STATIC_INCLUDE_DIRS:INTERNAL= -_OPENSSL_STATIC_LDFLAGS:INTERNAL=-lssl;-ldl;-lcrypto;-ldl -_OPENSSL_STATIC_LDFLAGS_OTHER:INTERNAL= -_OPENSSL_STATIC_LIBDIR:INTERNAL= -_OPENSSL_STATIC_LIBRARIES:INTERNAL=ssl;dl;crypto;dl -_OPENSSL_STATIC_LIBRARY_DIRS:INTERNAL= -_OPENSSL_STATIC_LIBS:INTERNAL= -_OPENSSL_STATIC_LIBS_L:INTERNAL= -_OPENSSL_STATIC_LIBS_OTHER:INTERNAL= -_OPENSSL_STATIC_LIBS_PATHS:INTERNAL= -_OPENSSL_VERSION:INTERNAL=1.1.0g -_OPENSSL_openssl_INCLUDEDIR:INTERNAL= -_OPENSSL_openssl_LIBDIR:INTERNAL= -_OPENSSL_openssl_PREFIX:INTERNAL= -_OPENSSL_openssl_VERSION:INTERNAL= -__pkg_config_arguments__OPENSSL:INTERNAL=QUIET;openssl -__pkg_config_checked__OPENSSL:INTERNAL=1 -prefix_result:INTERNAL=/usr/lib/x86_64-linux-gnu - diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 24048cd4..4a0b6b76 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -46,7 +46,7 @@ public: virtual bool process_withdrawal(const son_wallet_withdraw_object &swwo) = 0; virtual std::string process_sidechain_transaction(const sidechain_transaction_object &sto) = 0; virtual std::string send_sidechain_transaction(const sidechain_transaction_object &sto) = 0; - virtual int64_t settle_sidechain_transaction(const sidechain_transaction_object &sto) = 0; + virtual bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) = 0; protected: peerplays_sidechain_plugin &plugin; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index eb218a4c..a09ccb9b 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -95,7 +95,7 @@ public: 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); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); private: std::string ip; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index b99b3c22..df3cde24 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -19,7 +19,6 @@ public: std::string account_history_api_get_transaction(std::string transaction_id); std::string block_api_get_block(uint32_t block_number); std::string condenser_api_get_config(); - std::string condenser_api_get_transaction(std::string transaction_id); std::string database_api_get_dynamic_global_properties(); std::string database_api_get_version(); std::string network_broadcast_api_broadcast_transaction(std::string htrx); @@ -28,6 +27,7 @@ public: std::string get_head_block_id(); std::string get_head_block_time(); std::string get_is_test_net(); + std::string get_last_irreversible_block_num(); }; class hive_wallet_rpc_client : public rpc_client { @@ -57,7 +57,7 @@ public: 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); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); private: std::string node_ip; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp index 078700f4..ac0a82e5 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp @@ -20,7 +20,7 @@ public: 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); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); private: }; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 7790faee..d5ec94a1 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -549,9 +549,10 @@ void sidechain_net_handler::settle_sidechain_transactions() { ilog("Sidechain transaction to settle: ${sto}", ("sto", sto.id)); - int64_t settle_amount = settle_sidechain_transaction(sto); + asset settle_amount; + bool settle_sidechain_result = settle_sidechain_transaction(sto, settle_amount); - if (settle_amount < 0) { + if (settle_sidechain_result == false) { wlog("Sidechain transaction not settled: ${sto}", ("sto", sto.id)); return; } @@ -568,12 +569,12 @@ void sidechain_net_handler::settle_sidechain_transactions() { sts_op.sidechain_transaction_id = sto.id; proposal_op.proposed_ops.emplace_back(sts_op); - if (settle_amount != 0) { + if (settle_amount.amount != 0) { if (sto.object_id.is()) { asset_issue_operation ai_op; ai_op.fee = asset(2001000); ai_op.issuer = gpo.parameters.son_account(); - ai_op.asset_to_issue = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); + ai_op.asset_to_issue = settle_amount; ai_op.issue_to_account = database.get(sto.object_id).peerplays_from; proposal_op.proposed_ops.emplace_back(ai_op); } @@ -582,7 +583,7 @@ void sidechain_net_handler::settle_sidechain_transactions() { asset_reserve_operation ar_op; ar_op.fee = asset(2001000); ar_op.payer = gpo.parameters.son_account(); - ar_op.amount_to_reserve = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); + ar_op.amount_to_reserve = settle_amount; proposal_op.proposed_ops.emplace_back(ar_op); } } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 9bcd3007..dcad57e7 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1484,16 +1484,15 @@ std::string sidechain_net_handler_bitcoin::send_sidechain_transaction(const side return send_transaction(sto); } -int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain_transaction_object &sto) { +bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { if (sto.object_id.is()) { - return 0; + settle_amount = asset(0, database.get_global_properties().parameters.btc_asset()); + return true; } - int64_t settle_amount = -1; - if (sto.sidechain_transaction.empty()) { - return settle_amount; + return false; } std::string tx_str = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true); @@ -1502,7 +1501,7 @@ int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidech boost::property_tree::read_json(tx_ss, tx_json); if ((tx_json.count("error")) && (!tx_json.get_child("error").empty())) { - return settle_amount; + return false; } const chain::global_property_object &gpo = database.get_global_properties(); @@ -1533,15 +1532,17 @@ int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidech } } } - settle_amount = tx_amount; + settle_amount = asset(tx_amount, database.get_global_properties().parameters.btc_asset()); + return true; } if (sto.object_id.is()) { auto swwo = database.get(sto.object_id); - settle_amount = swwo.withdraw_amount.value; + settle_amount = swwo.withdraw_amount; + return true; } } - return settle_amount; + return false; } std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const std::vector &son_pubkeys) { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index b3c4bf50..bdc8c276 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -34,12 +34,12 @@ hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std: std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { std::string params = "{ \"id\": \"" + transaction_id + "\" }"; - return send_post_request("account_history_api.get_transaction", params, false); + return send_post_request("account_history_api.get_transaction", params, true); } std::string hive_node_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, false); + return send_post_request("block_api.get_block", params, true); } std::string hive_node_rpc_client::condenser_api_get_config() { @@ -47,11 +47,6 @@ std::string hive_node_rpc_client::condenser_api_get_config() { return send_post_request("condenser_api.get_config", params, false); } -std::string hive_node_rpc_client::condenser_api_get_transaction(std::string transaction_id) { - std::string params = "[\"" + transaction_id + "\"]"; - return send_post_request("condenser_api.get_transaction", params, false); -} - std::string hive_node_rpc_client::database_api_get_dynamic_global_properties() { return send_post_request("database_api.get_dynamic_global_properties", "", false); } @@ -85,6 +80,11 @@ std::string hive_node_rpc_client::get_is_test_net() { return retrieve_value_from_reply(reply_str, "IS_TEST_NET"); } +std::string hive_node_rpc_client::get_last_irreversible_block_num() { + std::string reply_str = database_api_get_dynamic_global_properties(); + return retrieve_value_from_reply(reply_str, "last_irreversible_block_num"); +} + hive_wallet_rpc_client::hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : rpc_client(_ip, _port, _user, _password) { } @@ -803,9 +803,47 @@ std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidecha return htrx.id().str(); } -int64_t sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_transaction_object &sto) { - int64_t settle_amount = 0; - return settle_amount; +bool sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { + + if (sto.object_id.is()) { + settle_amount.amount = 0; + return true; + } + + if (sto.sidechain_transaction.empty()) { + return false; + } + + std::string tx_str = node_rpc_client->account_history_api_get_transaction(sto.sidechain_transaction); + if (tx_str != "") { + + std::stringstream ss_tx(tx_str); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(ss_tx, tx_json); + + //const chain::global_property_object &gpo = database.get_global_properties(); + + std::string tx_txid = tx_json.get("result.transaction_id"); + uint32_t tx_block_num = tx_json.get("result.block_num"); + uint32_t last_irreversible_block = std::stoul(node_rpc_client->get_last_irreversible_block_num()); + + //std::string tx_address = addr.get_address(); + //int64_t tx_amount = -1; + + if (tx_block_num <= last_irreversible_block) { + if (sto.object_id.is()) { + auto swwo = database.get(sto.object_id); + if (swwo.withdraw_currency == "HBD") { + settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.hbd_asset()); + } + if (swwo.withdraw_currency == "HIVE") { + settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.hive_asset()); + } + return true; + } + } + } + return false; } void sidechain_net_handler_hive::schedule_hive_listener() { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 641d9abf..d5a9ec32 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -25,12 +25,12 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::peerplays; - const auto &assets_by_symbol = database.get_index_type().indices().get(); - const auto get_asset_id = [&assets_by_symbol](const string &symbol) { - auto asset_itr = assets_by_symbol.find(symbol); - FC_ASSERT(asset_itr != assets_by_symbol.end(), "Unable to find asset '${sym}'", ("sym", symbol)); - return asset_itr->get_id(); - }; + //const auto &assets_by_symbol = database.get_index_type().indices().get(); + //const auto get_asset_id = [&assets_by_symbol](const string &symbol) { + // auto asset_itr = assets_by_symbol.find(symbol); + // FC_ASSERT(asset_itr != assets_by_symbol.end(), "Unable to find asset '${sym}'", ("sym", symbol)); + // return asset_itr->get_id(); + //}; //tracked_assets.push_back(get_asset_id("PBTC")); //tracked_assets.push_back(get_asset_id("PETH")); //tracked_assets.push_back(get_asset_id("PEOS")); @@ -271,9 +271,23 @@ std::string sidechain_net_handler_peerplays::send_sidechain_transaction(const si return ""; } -int64_t sidechain_net_handler_peerplays::settle_sidechain_transaction(const sidechain_transaction_object &sto) { - int64_t settle_amount = 0; - return settle_amount; +bool sidechain_net_handler_peerplays::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { + + if (sto.object_id.is()) { + settle_amount = asset(0); + } + + if (sto.object_id.is()) { + //auto swdo = database.get(sto.object_id); + //settle_amount = asset(swdo.sidechain_amount, swdo.sidechain_currency); + } + + if (sto.object_id.is()) { + auto swwo = database.get(sto.object_id); + settle_amount = swwo.peerplays_asset; + } + + return true; } }} // namespace graphene::peerplays_sidechain -- 2.45.2 From 11b64ffb8a23dacaa77d1d6b665434195ce3b6df Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 28 Jun 2021 23:18:19 +0200 Subject: [PATCH 22/57] Refactor tracked_assets --- .../peerplays_sidechain/hive/transaction.cpp | 28 +--------- .../sidechain_net_handler.hpp | 2 - .../sidechain_net_handler_hive.hpp | 6 -- .../sidechain_net_handler.cpp | 38 +++++-------- .../sidechain_net_handler_bitcoin.cpp | 5 +- .../sidechain_net_handler_hive.cpp | 56 +++---------------- 6 files changed, 24 insertions(+), 111 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp index 0e0ff8ed..3e4a59f5 100644 --- a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp @@ -43,23 +43,7 @@ void signed_transaction::clear() { const signature_type &signed_transaction::sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) { digest_type h = sig_digest(chain_id); - auto sig = key.sign_compact(h, true); - - ilog("Signing1: chain_id = ${chain_id}", ("chain_id", chain_id)); - ilog("Signing1: key = ${key}", ("key", key)); - ilog("Signing1: this = ${this}", ("this", *this)); - ilog("Signing1: h = ${h}", ("h", h)); - ilog("Signing1: signature = ${sig}", ("sig", sig)); - - std::stringstream ss_st; - fc::raw::pack(ss_st, chain_id); - ilog("Signing: ${ss_st}", ("ss_st", boost::algorithm::hex(ss_st.str()))); - - ss_st.str(""); - fc::raw::pack(ss_st, *this); - ilog("Signing: ${ss_st}", ("ss_st", boost::algorithm::hex(ss_st.str()))); - - signatures.push_back(sig); + signatures.push_back(key.sign_compact(h, true)); return signatures.back(); } @@ -67,15 +51,7 @@ signature_type signed_transaction::sign(const hive::private_key_type &key, const digest_type::encoder enc; fc::raw::pack(enc, chain_id); fc::raw::pack(enc, *this); - auto sig = key.sign_compact(enc.result(), true); - - ilog("Signing2: chain_id = ${chain_id}", ("chain_id", chain_id)); - ilog("Signing2: key = ${key}", ("key", key)); - ilog("Signing2: this = ${this}", ("this", *this)); - ilog("Signing2: h = ${h}", ("h", enc.result())); - ilog("Signing2: signature = ${sig}", ("sig", sig)); - - return sig; + return key.sign_compact(enc.result(), true); } }}} // namespace graphene::peerplays_sidechain::hive diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 4a0b6b76..022008e0 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -55,8 +55,6 @@ protected: std::map private_keys; - std::vector tracked_assets; - bool is_tracked_asset(asset_id_type asset_id); void on_applied_block(const signed_block &b); private: diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index df3cde24..9d1291ef 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -35,12 +35,6 @@ public: hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); std::string get_account(std::string account); - std::string info(); - std::string lock(); - std::string unlock(std::string password); - std::string update_account_auth_key(std::string account_name, std::string type, std::string public_key, std::string weight); - std::string update_account_auth_account(std::string account_name, std::string type, std::string auth_account, std::string weight); - std::string update_account_auth_threshold(std::string account_name, std::string type, std::string threshold); std::string get_account_memo_key(std::string account); }; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index d5ec94a1..2d2fef25 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -180,19 +180,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) || enable_peerplays_asset_deposits); - bool is_tracked_asset = false; - if (sed.sidechain == sidechain_type::peerplays) { - for (const auto &asset_id : tracked_assets) { - std::string asset_id_str = asset_id_to_string(asset_id); - if (sed.sidechain_currency == asset_id_str) { - is_tracked_asset = true; - break; - } - } - } - bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) && - is_tracked_asset; + ((sed.sidechain_currency == asset_id_to_string(gpo.parameters.btc_asset())) || + (sed.sidechain_currency == asset_id_to_string(gpo.parameters.hbd_asset())) || + (sed.sidechain_currency == asset_id_to_string(gpo.parameters.hive_asset()))); // Deposit request if (deposit_condition) { @@ -600,18 +591,10 @@ void sidechain_net_handler::settle_sidechain_transactions() { }); } -bool sidechain_net_handler::is_tracked_asset(asset_id_type asset_id) { - bool is_tracked_asset = false; - for (const auto &tracked_asset_id : tracked_assets) { - if (asset_id == tracked_asset_id) { - is_tracked_asset = true; - break; - } - } - return is_tracked_asset; -} - void sidechain_net_handler::on_applied_block(const signed_block &b) { + + const chain::global_property_object &gpo = plugin.database().get_global_properties(); + for (const auto &trx : b.transactions) { size_t operation_index = -1; for (auto op : trx.operations) { @@ -619,11 +602,16 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) { if (op.which() == operation::tag::value) { transfer_operation transfer_op = op.get(); - if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) { + if (transfer_op.to != gpo.parameters.son_account()) { continue; } - if (!is_tracked_asset(transfer_op.amount.asset_id)) { + bool is_tracked_asset = + ((sidechain == sidechain_type::bitcoin) && (transfer_op.amount.asset_id == gpo.parameters.btc_asset())) || + ((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hbd_asset())) || + ((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hive_asset())); + + if (!is_tracked_asset) { continue; } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index dcad57e7..3db9991c 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -910,7 +910,6 @@ void zmq_listener::handle_zmq() { sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::bitcoin; - tracked_assets.push_back(database.get_global_properties().parameters.btc_asset()); ip = options.at("bitcoin-node-ip").as(); zmq_port = options.at("bitcoin-node-zmq-port").as(); @@ -990,7 +989,7 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() { bool sidechain_net_handler_bitcoin::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())); + //ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); bool should_approve = false; @@ -1379,7 +1378,7 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() { plugin.app().p2p_node()->broadcast(net::trx_message(trx)); retval = true; } catch (fc::exception &e) { - elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + elog("Sending transaction for sidechain address update operation failed with exception ${e}", ("e", e.what())); retval = false; } } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index bdc8c276..23ce1bac 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -34,12 +34,12 @@ hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std: std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { std::string params = "{ \"id\": \"" + transaction_id + "\" }"; - return send_post_request("account_history_api.get_transaction", params, true); + return send_post_request("account_history_api.get_transaction", params, false); } std::string hive_node_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); + return send_post_request("block_api.get_block", params, false); } std::string hive_node_rpc_client::condenser_api_get_config() { @@ -57,7 +57,7 @@ std::string hive_node_rpc_client::database_api_get_version() { std::string hive_node_rpc_client::network_broadcast_api_broadcast_transaction(std::string htrx) { std::string params = "{ \"trx\": " + htrx + ", \"max_block_age\": -1 }"; - return send_post_request("network_broadcast_api.broadcast_transaction", params, true); + return send_post_request("network_broadcast_api.broadcast_transaction", params, false); } std::string hive_node_rpc_client::get_chain_id() { @@ -91,35 +91,7 @@ hive_wallet_rpc_client::hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string hive_wallet_rpc_client::get_account(std::string account) { std::string params = "[\"" + account + "\"]"; - return send_post_request("get_account", params, true); -} - -std::string hive_wallet_rpc_client::lock() { - return send_post_request("lock", "", true); -} - -std::string hive_wallet_rpc_client::info() { - return send_post_request("info", "", true); -} - -std::string hive_wallet_rpc_client::unlock(std::string password) { - std::string params = "[\"" + password + "\"]"; - return send_post_request("unlock", params, true); -} - -std::string hive_wallet_rpc_client::update_account_auth_key(std::string account_name, std::string type, std::string public_key, std::string weight) { - std::string params = "[\"" + account_name + "\", \"" + type + "\", \"" + public_key + "\", " + weight + "]"; - return send_post_request("update_account_auth_key", params, true); -} - -std::string hive_wallet_rpc_client::update_account_auth_account(std::string account_name, std::string type, std::string auth_account, std::string weight) { - std::string params = "[\"" + account_name + "\", \"" + type + "\", \"" + auth_account + "\", " + weight + "]"; - return send_post_request("update_account_auth_account", params, true); -} - -std::string hive_wallet_rpc_client::update_account_auth_threshold(std::string account_name, std::string type, std::string threshold) { - std::string params = "[\"" + account_name + "\", \"" + type + "\", " + threshold + "]"; - return send_post_request("update_account_auth_account", params, true); + return send_post_request("get_account", params, false); } std::string hive_wallet_rpc_client::get_account_memo_key(std::string account) { @@ -130,8 +102,6 @@ std::string hive_wallet_rpc_client::get_account_memo_key(std::string account) { 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; - tracked_assets.push_back(database.get_global_properties().parameters.hbd_asset()); - tracked_assets.push_back(database.get_global_properties().parameters.hive_asset()); node_ip = options.at("hive-node-ip").as(); node_rpc_port = options.at("hive-node-rpc-port").as(); @@ -214,7 +184,7 @@ 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())); + //ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); bool should_approve = false; @@ -280,7 +250,6 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str)); hive::signed_transaction op_trx; fc::raw::unpack(ss_trx, op_trx, 1000); - ilog("TRX: ${op_trx}", ("op_trx", op_trx)); fc::flat_map account_auths; uint32_t total_weight = 0; @@ -306,7 +275,6 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { htrx.set_expiration(op_trx.expiration); htrx.operations.push_back(auo); - ilog("TRX: ${htrx}", ("htrx", htrx)); std::stringstream ss; fc::raw::pack(ss, htrx, 1000); @@ -428,7 +396,6 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str)); hive::signed_transaction op_trx; fc::raw::unpack(ss_trx, op_trx, 1000); - ilog("TRX: ${op_trx}", ("op_trx", op_trx)); uint64_t symbol = 0; if (swwo->withdraw_currency == "HBD") { @@ -451,7 +418,6 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { htrx.set_expiration(op_trx.expiration); htrx.operations.push_back(t_op); - ilog("TRX: ${htrx}", ("htrx", htrx)); std::stringstream ss; fc::raw::pack(ss, htrx, 1000); @@ -552,7 +518,6 @@ void sidechain_net_handler_hive::process_primary_wallet() { htrx.set_expiration(head_block_time + fc::seconds(90)); htrx.operations.push_back(auo); - ilog("TRX: ${htrx}", ("htrx", htrx)); std::stringstream ss; fc::raw::pack(ss, htrx, 1000); @@ -625,7 +590,7 @@ void sidechain_net_handler_hive::process_sidechain_addresses() { 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())); + elog("Sending transaction for sidechain address update operation failed with exception ${e}", ("e", e.what())); retval = false; } } @@ -713,7 +678,6 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob htrx.set_expiration(head_block_time + fc::seconds(90)); htrx.operations.push_back(t_op); - ilog("TRX: ${htrx}", ("htrx", htrx)); std::stringstream ss; fc::raw::pack(ss, htrx, 1000); @@ -750,7 +714,7 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob 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())); + elog("Sending proposal for withdraw sidechain transaction create operation failed with exception ${e}", ("e", e.what())); return false; } @@ -763,16 +727,12 @@ std::string sidechain_net_handler_hive::process_sidechain_transaction(const side hive::signed_transaction htrx; fc::raw::unpack(ss_trx, htrx, 1000); - ilog("TRX: ${htrx}", ("htrx", htrx)); - std::string chain_id_str = node_rpc_client->get_chain_id(); const hive::chain_id_type chain_id(chain_id_str); fc::optional privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))); signature_type st = htrx.sign(*privkey, chain_id); - ilog("TRX: ${htrx}", ("htrx", htrx)); - std::stringstream ss_st; fc::raw::pack(ss_st, st, 1000); std::string st_str = boost::algorithm::hex(ss_st.str()); @@ -794,10 +754,8 @@ std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidecha htrx.signatures.push_back(st); } } - ilog("HTRX: ${htrx}", ("htrx", htrx)); std::string params = fc::json::to_string(htrx); - ilog("HTRX: ${htrx}", ("htrx", params)); node_rpc_client->network_broadcast_api_broadcast_transaction(params); return htrx.id().str(); -- 2.45.2 From 9344ed2778875ab2498d5a26b2ac00e9e0b3c2a9 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 5 Jul 2021 11:39:30 +0200 Subject: [PATCH 23/57] Update SON asset flags to enable full transfers --- libraries/chain/db_maint.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 6fe73b38..affbe404 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1925,10 +1925,7 @@ void database::perform_son_tasks() a.options.market_fee_percent = 500; // 5% a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; a.options.flags = asset_issuer_permission_flags::charge_market_fee | - //asset_issuer_permission_flags::white_list | - asset_issuer_permission_flags::override_authority | - asset_issuer_permission_flags::transfer_restricted | - asset_issuer_permission_flags::disable_confidential; + asset_issuer_permission_flags::override_authority; a.options.core_exchange_rate.base.amount = 100000; a.options.core_exchange_rate.base.asset_id = asset_id_type(0); a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value @@ -1962,10 +1959,7 @@ void database::perform_son_tasks() a.options.market_fee_percent = 500; // 5% a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; a.options.flags = asset_issuer_permission_flags::charge_market_fee | - //asset_issuer_permission_flags::white_list | - asset_issuer_permission_flags::override_authority | - asset_issuer_permission_flags::transfer_restricted | - asset_issuer_permission_flags::disable_confidential; + asset_issuer_permission_flags::override_authority; a.options.core_exchange_rate.base.amount = 100000; a.options.core_exchange_rate.base.asset_id = asset_id_type(0); a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value @@ -1999,10 +1993,7 @@ void database::perform_son_tasks() a.options.market_fee_percent = 500; // 5% a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; a.options.flags = asset_issuer_permission_flags::charge_market_fee | - //asset_issuer_permission_flags::white_list | - asset_issuer_permission_flags::override_authority | - asset_issuer_permission_flags::transfer_restricted | - asset_issuer_permission_flags::disable_confidential; + asset_issuer_permission_flags::override_authority; a.options.core_exchange_rate.base.amount = 100000; a.options.core_exchange_rate.base.asset_id = asset_id_type(0); a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value -- 2.45.2 From 143b244ccd8976ac35ff074bafda2888411b1df2 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 13 Jul 2021 13:47:50 +0200 Subject: [PATCH 24/57] Replace Hive cli_wallet RPC calls with Hive node RPC calls --- .../peerplays_sidechain/common/rpc_client.cpp | 29 ++++++++ .../peerplays_sidechain/common/rpc_client.hpp | 1 + .../sidechain_net_handler_hive.hpp | 18 +---- .../peerplays_sidechain_plugin.cpp | 7 -- .../sidechain_net_handler_hive.cpp | 71 ++++++++----------- 5 files changed, 61 insertions(+), 65 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index a2806ae5..661cb2c8 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -21,6 +21,35 @@ rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std:: authorization.val = "Basic " + fc::base64_encode(user + ":" + password); } +std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) { + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + if (json.find("result") == json.not_found()) { + return ""; + } + auto json_result = json.get_child("result"); + if (json_result.find(array_path) == json_result.not_found()) { + return ""; + } + + boost::property_tree::ptree array_ptree = json_result; + if (!array_path.empty()) { + array_ptree = json_result.get_child(array_path); + } + uint32_t array_el_idx = -1; + for (const auto &array_el : array_ptree) { + array_el_idx = array_el_idx + 1; + if (array_el_idx == idx) { + std::stringstream ss_res; + boost::property_tree::json_parser::write_json(ss_res, array_el.second); + return ss_res.str(); + } + } + + return ""; +} + std::string rpc_client::retrieve_value_from_reply(std::string reply_str, std::string value_path) { std::stringstream ss(reply_str); boost::property_tree::ptree json; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index 6ee56f72..edf1bb93 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -12,6 +12,7 @@ public: rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); 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); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 9d1291ef..3f0f7c3a 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -18,11 +18,14 @@ public: std::string account_history_api_get_transaction(std::string transaction_id); std::string block_api_get_block(uint32_t block_number); + std::string condenser_api_get_accounts(std::vector accounts); std::string condenser_api_get_config(); std::string database_api_get_dynamic_global_properties(); std::string database_api_get_version(); std::string network_broadcast_api_broadcast_transaction(std::string htrx); + std::string get_account(std::string account); + std::string get_account_memo_key(std::string account); std::string get_chain_id(); std::string get_head_block_id(); std::string get_head_block_time(); @@ -30,15 +33,6 @@ public: std::string get_last_irreversible_block_num(); }; -class hive_wallet_rpc_client : public rpc_client { -public: - hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); - - std::string get_account(std::string account); - - std::string get_account_memo_key(std::string account); -}; - 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); @@ -60,12 +54,6 @@ private: std::string node_rpc_password; hive_node_rpc_client *node_rpc_client; - std::string wallet_ip; - uint32_t wallet_rpc_port; - std::string wallet_rpc_user; - std::string wallet_rpc_password; - hive_wallet_rpc_client *wallet_rpc_client; - hive::chain_id_type chain_id; hive::network network_type; diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 979c47e7..13592d04 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -158,10 +158,6 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options( cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "Hive node RPC port"); cli.add_options()("hive-node-rpc-user", bpo::value(), "Hive node RPC user"); cli.add_options()("hive-node-rpc-password", bpo::value(), "Hive node RPC password"); - cli.add_options()("hive-wallet-ip", bpo::value()->default_value("127.0.0.1"), "Hive wallet IP address"); - cli.add_options()("hive-wallet-rpc-port", bpo::value()->default_value(28091), "Hive wallet RPC port "); - cli.add_options()("hive-wallet-rpc-user", bpo::value(), "Hive wallet RPC user"); - cli.add_options()("hive-wallet-rpc-password", bpo::value(), "Hive wallet RPC password"); cli.add_options()("hive-private-key", bpo::value>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4", "5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n")), "Tuple of [Hive public key, Hive private key] (may specify multiple times)"); @@ -234,9 +230,6 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt config_ready_hive = options.count("hive-node-ip") && options.count("hive-node-rpc-port") && /*options.count("hive-node-rpc-user") && options.count("hive-node-rpc-password") &&*/ - options.count("hive-wallet-ip") && - options.count("hive-wallet-rpc-port") && - /*options.count("hive-wallet-rpc-user") && options.count("hive-wallet-rpc-password") &&*/ options.count("hive-private-key"); if (!config_ready_hive) { wlog("Haven't set up Hive sidechain parameters"); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 23ce1bac..2770d2d1 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -42,6 +42,18 @@ std::string hive_node_rpc_client::block_api_get_block(uint32_t block_number) { return send_post_request("block_api.get_block", params, false); } +std::string hive_node_rpc_client::condenser_api_get_accounts(std::vector accounts) { + std::string params = ""; + for (auto account : accounts) { + if (!params.empty()) { + params = params + ","; + } + params = "\"" + account + "\""; + } + params = "[[" + params + "]]"; + return send_post_request("condenser_api.get_accounts", params, false); +} + std::string hive_node_rpc_client::condenser_api_get_config() { std::string params = "[]"; return send_post_request("condenser_api.get_config", params, false); @@ -60,6 +72,19 @@ std::string hive_node_rpc_client::network_broadcast_api_broadcast_transaction(st return send_post_request("network_broadcast_api.broadcast_transaction", params, false); } +std::string hive_node_rpc_client::get_account(std::string account) { + std::vector accounts; + accounts.push_back(account); + std::string reply_str = condenser_api_get_accounts(accounts); + return retrieve_array_value_from_reply(reply_str, "", 0); +} + +std::string hive_node_rpc_client::get_account_memo_key(std::string account) { + std::string reply_str = get_account(account); + reply_str = "{\"result\":" + reply_str + "}"; + return retrieve_value_from_reply(reply_str, "memo_key"); +} + std::string hive_node_rpc_client::get_chain_id() { std::string reply_str = database_api_get_version(); return retrieve_value_from_reply(reply_str, "chain_id"); @@ -85,20 +110,6 @@ std::string hive_node_rpc_client::get_last_irreversible_block_num() { return retrieve_value_from_reply(reply_str, "last_irreversible_block_num"); } -hive_wallet_rpc_client::hive_wallet_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : - rpc_client(_ip, _port, _user, _password) { -} - -std::string hive_wallet_rpc_client::get_account(std::string account) { - std::string params = "[\"" + account + "\"]"; - return send_post_request("get_account", params, false); -} - -std::string hive_wallet_rpc_client::get_account_memo_key(std::string account) { - std::string reply_str = get_account(account); - return retrieve_value_from_reply(reply_str, "memo_key"); -} - 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; @@ -116,19 +127,6 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi node_rpc_password = ""; } - wallet_ip = options.at("hive-wallet-ip").as(); - wallet_rpc_port = options.at("hive-wallet-rpc-port").as(); - if (options.count("hive-wallet-rpc-user")) { - wallet_rpc_user = options.at("hive-wallet-rpc-user").as(); - } else { - wallet_rpc_user = ""; - } - if (options.count("hive-wallet-rpc-password")) { - wallet_rpc_password = options.at("hive-wallet-rpc-password").as(); - } else { - wallet_rpc_password = ""; - } - if (options.count("hive-private-key")) { const std::vector pub_priv_keys = options["hive-private-key"].as>(); for (const std::string &itr_key_pair : pub_priv_keys) { @@ -148,17 +146,9 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); FC_ASSERT(false); } - try { - conn.connect_to(fc::ip::endpoint(fc::ip::address(wallet_ip), wallet_rpc_port)); - } catch (fc::exception &e) { - elog("No Hive wallet running at ${ip} or wrong rpc port: ${port}", ("ip", wallet_ip)("port", wallet_rpc_port)); - FC_ASSERT(false); - } node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password); - wallet_rpc_client = new hive_wallet_rpc_client(wallet_ip, wallet_rpc_port, wallet_rpc_user, wallet_rpc_password); - std::string chain_id_str = node_rpc_client->get_chain_id(); chain_id = chain_id_type(chain_id_str); @@ -183,7 +173,6 @@ 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; @@ -258,7 +247,7 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { account_auths[wallet_son.sidechain_public_keys.at(sidechain)] = wallet_son.weight; } - std::string memo_key = wallet_rpc_client->get_account_memo_key("son-account"); + std::string memo_key = node_rpc_client->get_account_memo_key("son-account"); hive::authority active; active.weight_threshold = total_weight * 2 / 3 + 1; @@ -493,7 +482,8 @@ void sidechain_net_handler_hive::process_primary_wallet() { account_auths[active_son.sidechain_public_keys.at(sidechain)] = active_son.weight; } - std::string memo_key = wallet_rpc_client->get_account_memo_key("son-account"); + std::string memo_key = node_rpc_client->get_account_memo_key("son-account"); + if (memo_key.empty()) { return; } @@ -600,7 +590,6 @@ void sidechain_net_handler_hive::process_sidechain_addresses() { } bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object &swdo) { - const chain::global_property_object &gpo = database.get_global_properties(); price asset_price; @@ -647,7 +636,6 @@ bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object } bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_object &swwo) { - const chain::global_property_object &gpo = database.get_global_properties(); //===== @@ -722,7 +710,6 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob } std::string sidechain_net_handler_hive::process_sidechain_transaction(const sidechain_transaction_object &sto) { - std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); hive::signed_transaction htrx; fc::raw::unpack(ss_trx, htrx, 1000); @@ -741,7 +728,6 @@ std::string sidechain_net_handler_hive::process_sidechain_transaction(const side } std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidechain_transaction_object &sto) { - std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); hive::signed_transaction htrx; fc::raw::unpack(ss_trx, htrx, 1000); @@ -762,7 +748,6 @@ std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidecha } bool sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { - if (sto.object_id.is()) { settle_amount.amount = 0; return true; -- 2.45.2 From a55a4ecaadf11582ec1d83e921f0034dbc5956d5 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 19 Jul 2021 13:31:56 +0200 Subject: [PATCH 25/57] Separate sidechain transaction signed/reported counters by sidechain --- libraries/chain/db_maint.cpp | 32 ++++++++++++------- .../include/graphene/chain/son_object.hpp | 8 ++--- .../chain/sidechain_transaction_evaluator.cpp | 10 +++++- .../chain/son_wallet_deposit_evaluator.cpp | 16 ++++++++-- .../chain/son_wallet_withdraw_evaluator.cpp | 16 ++++++++-- tests/tests/son_operations_tests.cpp | 24 ++++++++++---- 6 files changed, 78 insertions(+), 28 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index affbe404..20af13c4 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -210,20 +210,29 @@ void database::pay_sons() if( now < HARDFORK_SON2_TIME ) { son_weight = get_weight_before_son2_hf(_vote_tally_buffer[son_obj->vote_id]); } - weighted_total_txs_signed += (s.txs_signed * son_weight); + uint64_t txs_signed = 0; + for (const auto &ts : s.txs_signed) { + txs_signed = txs_signed + ts.second; + } + weighted_total_txs_signed += (txs_signed * son_weight); }); // Now pay off each SON proportional to the number of transactions signed. get_index_type().inspect_all_objects([this, &weighted_total_txs_signed, &dpo, &son_budget, &get_weight, &get_weight_before_son2_hf, &now](const object& o) { const son_statistics_object& s = static_cast(o); - if(s.txs_signed > 0){ + uint64_t txs_signed = 0; + for (const auto &ts : s.txs_signed) { + txs_signed = txs_signed + ts.second; + } + + if(txs_signed > 0){ const auto& idx = get_index_type().indices().get(); auto son_obj = idx.find( s.owner ); auto son_weight = get_weight(_vote_tally_buffer[son_obj->vote_id]); if( now < HARDFORK_SON2_TIME ) { son_weight = get_weight_before_son2_hf(_vote_tally_buffer[son_obj->vote_id]); } - share_type pay = (s.txs_signed * son_weight * son_budget.value)/weighted_total_txs_signed; + share_type pay = (txs_signed * son_weight * son_budget.value)/weighted_total_txs_signed; modify( *son_obj, [&]( son_object& _son_obj) { _son_obj.pay_son_fee(pay, *this); @@ -236,8 +245,9 @@ void database::pay_sons() //Reset the tx counter in each son statistics object modify( s, [&]( son_statistics_object& _s) { - _s.total_txs_signed += _s.txs_signed; - _s.txs_signed = 0; + for (const auto &ts : s.txs_signed) { + _s.txs_signed.at(ts.first) = 0; + } }); } }); @@ -593,7 +603,7 @@ void database::update_active_committee_members() update_committee_member_total_votes( cm ); } } - + // Update committee authorities if( !committee_members.empty() ) { @@ -1243,13 +1253,13 @@ double database::calculate_vesting_factor(const account_object& stake_account) // variables needed const auto number_of_subperiods = vesting_period / vesting_subperiod; double vesting_factor; - + // get in what sub period we are uint32_t current_subperiod = get_gpos_current_subperiod(); - + if(current_subperiod == 0 || current_subperiod > number_of_subperiods) return 0; - // On starting new vesting period, all votes become zero until someone votes, To avoid a situation of zero votes, + // On starting new vesting period, all votes become zero until someone votes, To avoid a situation of zero votes, // changes were done to roll in GPOS rules, the vesting factor will be 1 for whoever votes in 6th sub-period of last vesting period // BLOCKBACK-174 fix if(current_subperiod == 1 && this->head_block_time() >= HARDFORK_GPOS_TIME + vesting_period) //Applicable only from 2nd vesting period @@ -2176,7 +2186,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g } } } tally_helper(*this, gpo); - + perform_account_maintenance( tally_helper ); struct clear_canary { clear_canary(vector& target): target(target){} @@ -2222,7 +2232,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g if( !p.pending_parameters->extensions.value.gpos_subperiod.valid() ) p.pending_parameters->extensions.value.gpos_subperiod = p.parameters.extensions.value.gpos_subperiod; if( !p.pending_parameters->extensions.value.gpos_vesting_lockin_period.valid() ) - p.pending_parameters->extensions.value.gpos_vesting_lockin_period = p.parameters.extensions.value.gpos_vesting_lockin_period; + p.pending_parameters->extensions.value.gpos_vesting_lockin_period = p.parameters.extensions.value.gpos_vesting_lockin_period; if( !p.pending_parameters->extensions.value.rbac_max_permissions_per_account.valid() ) p.pending_parameters->extensions.value.rbac_max_permissions_per_account = p.parameters.extensions.value.rbac_max_permissions_per_account; if( !p.pending_parameters->extensions.value.rbac_max_account_authority_lifetime.valid() ) diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 53072515..8c0e32dc 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -31,9 +31,9 @@ namespace graphene { namespace chain { son_id_type owner; // Lifetime total transactions signed - uint64_t total_txs_signed = 0; + flat_map total_txs_signed; // Transactions signed since the last son payouts - uint64_t txs_signed = 0; + flat_map txs_signed; // Total Voted Active time i.e. duration selected as part of voted active SONs uint64_t total_voted_time = 0; // Total Downtime barring the current down time in seconds, used for stats to present to user @@ -47,9 +47,9 @@ namespace graphene { namespace chain { // Deregistered Timestamp fc::time_point_sec deregistered_timestamp; // Total sidechain transactions reported by SON network while SON was active - uint64_t total_sidechain_txs_reported = 0; + flat_map total_sidechain_txs_reported; // Sidechain transactions reported by this SON - uint64_t sidechain_txs_reported = 0; + flat_map sidechain_txs_reported; }; /** diff --git a/libraries/chain/sidechain_transaction_evaluator.cpp b/libraries/chain/sidechain_transaction_evaluator.cpp index 12bf2f42..a56216fe 100644 --- a/libraries/chain/sidechain_transaction_evaluator.cpp +++ b/libraries/chain/sidechain_transaction_evaluator.cpp @@ -97,7 +97,15 @@ object_id_type sidechain_transaction_sign_evaluator::do_apply(const sidechain_tr }); db().modify(son_obj->statistics(db()), [&](son_statistics_object& sso) { - sso.txs_signed += 1; + if (sso.total_txs_signed.find(sto_obj->sidechain) == sso.total_txs_signed.end()) { + sso.total_txs_signed[sto_obj->sidechain] = 0; + } + sso.total_txs_signed[sto_obj->sidechain] += 1; + + if (sso.txs_signed.find(sto_obj->sidechain) == sso.txs_signed.end()) { + sso.txs_signed[sto_obj->sidechain] = 0; + } + sso.txs_signed[sto_obj->sidechain] += 1; }); return op.sidechain_transaction_id; diff --git a/libraries/chain/son_wallet_deposit_evaluator.cpp b/libraries/chain/son_wallet_deposit_evaluator.cpp index 24a87e47..f9620282 100644 --- a/libraries/chain/son_wallet_deposit_evaluator.cpp +++ b/libraries/chain/son_wallet_deposit_evaluator.cpp @@ -84,9 +84,16 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de auto stats_itr = db().get_index_type().indices().get().find(si.son_id); db().modify(*stats_itr, [&op, &si](son_statistics_object &sso) { - sso.total_sidechain_txs_reported = sso.total_sidechain_txs_reported + 1; + if (sso.total_sidechain_txs_reported.find(op.sidechain) == sso.total_sidechain_txs_reported.end()) { + sso.total_sidechain_txs_reported[op.sidechain] = 0; + } + sso.total_sidechain_txs_reported[op.sidechain] += 1; + if (si.son_id == op.son_id) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; } }); } @@ -122,7 +129,10 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de }); auto stats_itr = db().get_index_type().indices().get().find(op.son_id); db().modify(*stats_itr, [&op](son_statistics_object &sso) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; }); return (*itr).id; } diff --git a/libraries/chain/son_wallet_withdraw_evaluator.cpp b/libraries/chain/son_wallet_withdraw_evaluator.cpp index bf6adaf9..2110e49d 100644 --- a/libraries/chain/son_wallet_withdraw_evaluator.cpp +++ b/libraries/chain/son_wallet_withdraw_evaluator.cpp @@ -82,9 +82,16 @@ object_id_type create_son_wallet_withdraw_evaluator::do_apply(const son_wallet_w auto stats_itr = db().get_index_type().indices().get().find(si.son_id); db().modify(*stats_itr, [&op, &si](son_statistics_object &sso) { - sso.total_sidechain_txs_reported = sso.total_sidechain_txs_reported + 1; + if (sso.total_sidechain_txs_reported.find(op.sidechain) == sso.total_sidechain_txs_reported.end()) { + sso.total_sidechain_txs_reported[op.sidechain] = 0; + } + sso.total_sidechain_txs_reported[op.sidechain] += 1; + if (si.son_id == op.son_id) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; } }); } @@ -120,7 +127,10 @@ object_id_type create_son_wallet_withdraw_evaluator::do_apply(const son_wallet_w }); auto stats_itr = db().get_index_type().indices().get().find(op.son_id); db().modify(*stats_itr, [&op](son_statistics_object &sso) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; }); return (*itr).id; } diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 5fee05d5..f66cbd48 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -491,12 +491,20 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) // Modify the transaction signed statistics of Alice's SON db.modify( *son_stats_obj1, [&]( son_statistics_object& _s) { - _s.txs_signed = 2; + _s.txs_signed[sidechain_type::bitcoin] = 2; + _s.txs_signed[sidechain_type::hive] = 4; + + _s.total_txs_signed[sidechain_type::bitcoin] = 2; + _s.total_txs_signed[sidechain_type::hive] = 4; }); // Modify the transaction signed statistics of Bob's SON db.modify( *son_stats_obj2, [&]( son_statistics_object& _s) { - _s.txs_signed = 3; + _s.txs_signed[sidechain_type::bitcoin] = 3; + _s.txs_signed[sidechain_type::hive] = 6; + + _s.total_txs_signed[sidechain_type::bitcoin] = 3; + _s.total_txs_signed[sidechain_type::hive] = 6; }); // Note the balances before the maintenance @@ -506,11 +514,15 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) generate_blocks(dpo.next_maintenance_time); generate_block(); // Check if the signed transaction statistics are reset for both SONs - BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed, 0); - BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed, 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed.at(sidechain_type::hive), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed.at(sidechain_type::hive), 0); - BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed, 2); - BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed, 3); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed.at(sidechain_type::bitcoin), 2); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed.at(sidechain_type::hive), 4); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed.at(sidechain_type::bitcoin), 3); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed.at(sidechain_type::hive), 6); // Check that Alice and Bob are paid for signing the transactions in the previous day/cycle BOOST_REQUIRE_EQUAL(db.get_balance(obj1->son_account, asset_id_type()).amount.value, 80+obj1_balance); BOOST_REQUIRE_EQUAL(db.get_balance(obj2->son_account, asset_id_type()).amount.value, 120+obj2_balance); -- 2.45.2 From 380a1260bf07ef6c31dfc2c09f24a6f60c64b2e4 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 27 Jul 2021 23:41:00 +0200 Subject: [PATCH 26/57] Deposit from any Hive account to any Peerplays account --- .../sidechain_net_handler_hive.cpp | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 2770d2d1..3db5015a 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -313,7 +314,7 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { if (operation_type == "transfer_operation") { const auto &op_value = op.get_child("value"); - std::string address = op_value.get("from"); + std::string sidechain_from = op_value.get("from"); const auto &amount_child = op_value.get_child("amount"); @@ -327,7 +328,17 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { sidechain_currency = "HIVE"; } - process_ok = (swdo_sidechain_from == address) && + std::string memo = op_value.get("memo"); + if (!memo.empty()) { + boost::trim(memo); + if (memo.find("son-payment-to:") == 0) { + memo = memo.substr(15); + boost::trim(memo); + sidechain_from = memo; + } + } + + process_ok = (swdo_sidechain_from == sidechain_from) && (swdo_sidechain_currency == sidechain_currency) && (swdo_sidechain_amount == amount); } @@ -867,6 +878,16 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { sidechain_currency_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; } + std::string memo = op_value.get("memo"); + if (!memo.empty()) { + boost::trim(memo); + if (memo.find("son-payment-to:") == 0) { + memo = memo.substr(15); + boost::trim(memo); + from = memo; + } + } + if (to == "son-account") { const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum())); -- 2.45.2 From 3c6454cd8d03999f5d7469b78ec1e19d3c290de6 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 4 Aug 2021 19:00:00 +0200 Subject: [PATCH 27/57] Remove account name indicator string "son-payment-to:" --- .../sidechain_net_handler_hive.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 3db5015a..9eb861f5 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -329,13 +329,9 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { } std::string memo = op_value.get("memo"); + boost::trim(memo); if (!memo.empty()) { - boost::trim(memo); - if (memo.find("son-payment-to:") == 0) { - memo = memo.substr(15); - boost::trim(memo); - sidechain_from = memo; - } + sidechain_from = memo; } process_ok = (swdo_sidechain_from == sidechain_from) && @@ -879,13 +875,9 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { } std::string memo = op_value.get("memo"); + boost::trim(memo); if (!memo.empty()) { - boost::trim(memo); - if (memo.find("son-payment-to:") == 0) { - memo = memo.substr(15); - boost::trim(memo); - from = memo; - } + from = memo; } if (to == "son-account") { -- 2.45.2 From e8238f1cb404d4fea39b6b80451873c18bebcf78 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 9 Aug 2021 22:41:44 +0200 Subject: [PATCH 28/57] Reset sidechain_txs_reported counter on SON payout --- libraries/chain/db_maint.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 20af13c4..a0bdd089 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -248,6 +248,9 @@ void database::pay_sons() for (const auto &ts : s.txs_signed) { _s.txs_signed.at(ts.first) = 0; } + for (const auto &str : s.sidechain_txs_reported) { + _s.sidechain_txs_reported.at(str.first) = 0; + } }); } }); -- 2.45.2 From acb14325098823c603cdd281d0e0a6560f220450 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 18 Aug 2021 00:06:25 +0200 Subject: [PATCH 29/57] Allow deposit from Hive to account with no registered sidechain address --- .../sidechain_net_handler.hpp | 1 - .../sidechain_net_handler_bitcoin.hpp | 7 ++++--- .../sidechain_net_handler_hive.hpp | 10 +++------- .../sidechain_net_handler_peerplays.hpp | 2 -- .../sidechain_net_handler.cpp | 6 +++++- .../sidechain_net_handler_hive.cpp | 18 ++++++++++++++---- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 022008e0..3bf2a06b 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -4,7 +4,6 @@ #include -#include #include #include #include diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index a09ccb9b..32af7adf 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -1,13 +1,14 @@ #pragma once -#include #include #include #include +#include + #include -#include +#include namespace graphene { namespace peerplays_sidechain { @@ -68,7 +69,7 @@ class zmq_listener { public: zmq_listener(std::string _ip, uint32_t _zmq); - fc::signal event_received; + boost::signals2::signal event_received; private: void handle_zmq(); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 3f0f7c3a..842fe2a1 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -4,9 +4,9 @@ #include -#include -#include +#include +#include #include #include @@ -57,13 +57,9 @@ private: hive::chain_id_type chain_id; hive::network network_type; - std::string create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address); - std::string create_deposit_transaction(const son_wallet_deposit_object &swdo); - std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); - uint64_t last_block_received; fc::future _listener_task; - fc::signal event_received; + boost::signals2::signal event_received; void schedule_hive_listener(); void hive_listener_loop(); void handle_event(const std::string &event_data); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp index ac0a82e5..69eea1a9 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp @@ -4,8 +4,6 @@ #include -#include - namespace graphene { namespace peerplays_sidechain { class sidechain_net_handler_peerplays : public sidechain_net_handler { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 13205488..7d3314ab 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -415,7 +415,11 @@ void sidechain_net_handler::process_deposits() { const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_from, time_point_sec::maximum())); if (addr_itr == sidechain_addresses_idx.end()) { - return; + const auto &account_idx = database.get_index_type().indices().get(); + const auto &account_itr = account_idx.find(swdo.sidechain_from); + if (account_itr == account_idx.end()) { + return; + } } ilog("Deposit to process: ${swdo}", ("swdo", swdo)); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 9eb861f5..f11a5573 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -883,8 +883,18 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { if (to == "son-account") { const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum())); - if (addr_itr == sidechain_addresses_idx.end()) - continue; + account_id_type accn = account_id_type(); + if (addr_itr == sidechain_addresses_idx.end()) { + const auto &account_idx = database.get_index_type().indices().get(); + const auto &account_itr = account_idx.find(from); + if (account_itr == account_idx.end()) { + continue; + } else { + accn = account_itr->id; + } + } else { + accn = addr_itr->sidechain_address_account; + } std::stringstream ss; ss << "hive" @@ -894,14 +904,14 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { sidechain_event_data sed; sed.timestamp = database.head_block_time(); sed.block_num = database.head_block_num(); - sed.sidechain = addr_itr->sidechain; + sed.sidechain = sidechain; sed.sidechain_uid = sidechain_uid; sed.sidechain_transaction_id = transaction_id; sed.sidechain_from = from; sed.sidechain_to = to; sed.sidechain_currency = sidechain_currency; sed.sidechain_amount = amount; - sed.peerplays_from = addr_itr->sidechain_address_account; + sed.peerplays_from = accn; sed.peerplays_to = database.get_global_properties().parameters.son_account(); sed.peerplays_asset = asset(sed.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount); sidechain_event_data_received(sed); -- 2.45.2 From 73e4a0cc156ae9fe0af2065ac1d27af999ba090a Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 18 Aug 2021 00:07:03 +0200 Subject: [PATCH 30/57] Introduce option to enable/disable printing RPC calls to console --- .../peerplays_sidechain/common/rpc_client.cpp | 3 +- .../peerplays_sidechain/common/rpc_client.hpp | 3 +- .../sidechain_net_handler.hpp | 2 + .../sidechain_net_handler_bitcoin.hpp | 5 +- .../sidechain_net_handler_hive.hpp | 2 +- .../peerplays_sidechain_plugin.cpp | 6 +- .../sidechain_net_handler_bitcoin.cpp | 63 ++++++++++--------- .../sidechain_net_handler_hive.cpp | 24 ++++--- 8 files changed, 63 insertions(+), 45 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 661cb2c8..cb7c5251 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -11,11 +11,12 @@ namespace graphene { namespace peerplays_sidechain { -rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : +rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : ip(_ip), port(_port), user(_user), password(_password), + debug_rpc_calls(_debug_rpc_calls), request_id(0) { authorization.key = "Authorization"; authorization.val = "Basic " + fc::base64_encode(user + ":" + password); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index edf1bb93..c3edd145 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -9,7 +9,7 @@ namespace graphene { namespace peerplays_sidechain { class rpc_client { public: - rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); + rpc_client(std::string _ip, uint32_t _port, 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); @@ -20,6 +20,7 @@ protected: uint32_t port; std::string user; std::string password; + bool debug_rpc_calls; uint32_t request_id; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 3bf2a06b..21526d05 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -52,6 +52,8 @@ protected: graphene::chain::database &database; sidechain_type sidechain; + bool debug_rpc_calls; + std::map private_keys; void on_applied_block(const signed_block &b); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index 32af7adf..dd6ebb28 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -21,7 +21,7 @@ public: class bitcoin_rpc_client { public: - bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password); + bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password, bool _debug_rpc_calls); std::string addmultisigaddress(const uint32_t nrequired, const std::vector public_keys); std::string combinepsbt(const vector &psbts); @@ -51,7 +51,7 @@ public: //bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60); private: - fc::http::reply send_post_request(std::string body, bool show_log = false); + fc::http::reply send_post_request(std::string body, bool show_log); std::string ip; uint32_t rpc_port; @@ -59,6 +59,7 @@ private: std::string password; std::string wallet; std::string wallet_password; + bool debug_rpc_calls; fc::http::header authorization; }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 842fe2a1..675c3cdd 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -14,7 +14,7 @@ namespace graphene { namespace peerplays_sidechain { class hive_node_rpc_client : public rpc_client { public: - hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password); + hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, 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); diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 13592d04..ca258667 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -142,6 +142,8 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options( cli.add_options()("sidechain-retry-threshold", bpo::value()->default_value(150), "Sidechain retry throttling threshold"); + cli.add_options()("debug-rpc-calls", bpo::value()->default_value(false), "Outputs RPC calls to console"); + cli.add_options()("bitcoin-sidechain-enabled", bpo::value()->default_value(false), "Bitcoin sidechain handler enabled"); cli.add_options()("bitcoin-node-ip", bpo::value()->default_value("127.0.0.1"), "IP address of Bitcoin node"); cli.add_options()("bitcoin-node-zmq-port", bpo::value()->default_value(11111), "ZMQ port of Bitcoin node"); @@ -200,7 +202,9 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt } config_ready_son = config_ready_son && !private_keys.empty(); } - retries_threshold = options.at("sidechain-retry-threshold").as(); + if (options.count("sidechain-retry-threshold")) { + retries_threshold = options.at("sidechain-retry-threshold").as(); + } ilog("sidechain-retry-threshold: ${sidechain-retry-threshold}", ("sidechain-retry-threshold", retries_threshold)); } if (!config_ready_son) { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index fc248436..215071eb 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -26,13 +26,14 @@ namespace graphene { namespace peerplays_sidechain { // ============================================================================= -bitcoin_rpc_client::bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password) : +bitcoin_rpc_client::bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password, bool _debug_rpc_calls) : ip(_ip), rpc_port(_rpc), user(_user), password(_password), wallet(_wallet), - wallet_password(_wallet_password) { + wallet_password(_wallet_password), + debug_rpc_calls(_debug_rpc_calls) { authorization.key = "Authorization"; authorization.val = "Basic " + fc::base64_encode(user + ":" + password); } @@ -51,7 +52,7 @@ std::string bitcoin_rpc_client::addmultisigaddress(const uint32_t nrequired, con params = params + pubkeys + std::string("]"); body = body + params + std::string(", null, \"bech32\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -83,7 +84,7 @@ std::string bitcoin_rpc_client::combinepsbt(const vector &psbts) { params = params + std::string("\"") + psbt + std::string("\""); } body = body + params + std::string("]] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -120,7 +121,7 @@ std::string bitcoin_rpc_client::createmultisig(const uint32_t nrequired, const s params = params + pubkeys + std::string("]"); body = body + params + std::string(", \"p2sh-segwit\" ] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -162,7 +163,7 @@ std::string bitcoin_rpc_client::createpsbt(const std::vector &ins, co } body += std::string("]] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -206,7 +207,7 @@ std::string bitcoin_rpc_client::createrawtransaction(const std::vector bitcoin_rpc_client::listunspent(const uint32_t minconf, c "\"listunspent\", \"params\": [" + std::to_string(minconf) + "," + std::to_string(maxconf) + "] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); std::vector result; @@ -617,7 +618,7 @@ std::vector bitcoin_rpc_client::listunspent_by_address_and_amount(con body += std::to_string(minimum_amount); body += std::string("} ] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); std::vector result; if (reply.body.empty()) { @@ -652,7 +653,7 @@ std::string bitcoin_rpc_client::loadwallet(const std::string &filename) { "\"loadwallet\", \"params\": [\"" + filename + "\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -680,7 +681,7 @@ std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) { "\"method\": \"sendrawtransaction\", \"params\": [") + std::string("\"") + tx_hex + std::string("\"") + std::string("] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -707,7 +708,7 @@ std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string & std::string params = "\"" + tx_hash + "\""; body = body + params + std::string("]}"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -733,7 +734,7 @@ std::string bitcoin_rpc_client::unloadwallet(const std::string &filename) { "\"unloadwallet\", \"params\": [\"" + filename + "\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -760,7 +761,7 @@ std::string bitcoin_rpc_client::unloadwallet(const std::string &filename) { // std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletlock\", \"method\": " // "\"walletlock\", \"params\": [] }"); // -// const auto reply = send_post_request(body); +// const auto reply = send_post_request(body, debug_rpc_calls); // // if (reply.body.empty()) { // wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -788,7 +789,7 @@ std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { "\"walletprocesspsbt\", \"params\": [\"" + tx_psbt + "\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -814,7 +815,7 @@ std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { // "\"walletpassphrase\", \"params\": [\"" + // passphrase + "\", " + std::to_string(timeout) + "] }"); // -// const auto reply = send_post_request(body); +// const auto reply = send_post_request(body, debug_rpc_calls); // // if (reply.body.empty()) { // wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -911,6 +912,10 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::bitcoin; + if (options.count("debug-rpc-calls")) { + debug_rpc_calls = options.at("debug-rpc-calls").as(); + } + ip = options.at("bitcoin-node-ip").as(); zmq_port = options.at("bitcoin-node-zmq-port").as(); rpc_port = options.at("bitcoin-node-rpc-port").as(); @@ -945,7 +950,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain FC_ASSERT(false); } - bitcoin_client = std::unique_ptr(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password)); + bitcoin_client = std::unique_ptr(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password, debug_rpc_calls)); if (!wallet.empty()) { bitcoin_client->loadwallet(wallet); } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index f11a5573..64a1772c 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -29,18 +29,18 @@ namespace graphene { namespace peerplays_sidechain { -hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password) : - rpc_client(_ip, _port, _user, _password) { +hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : + rpc_client(_ip, _port, _user, _password, _debug_rpc_calls) { } std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { std::string params = "{ \"id\": \"" + transaction_id + "\" }"; - return send_post_request("account_history_api.get_transaction", params, false); + return send_post_request("account_history_api.get_transaction", params, debug_rpc_calls); } std::string hive_node_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, false); + return send_post_request("block_api.get_block", params, debug_rpc_calls); } std::string hive_node_rpc_client::condenser_api_get_accounts(std::vector accounts) { @@ -52,25 +52,25 @@ std::string hive_node_rpc_client::condenser_api_get_accounts(std::vector(); + } + node_ip = options.at("hive-node-ip").as(); node_rpc_port = options.at("hive-node-rpc-port").as(); if (options.count("hive-node-rpc-user")) { @@ -148,7 +152,7 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi FC_ASSERT(false); } - node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password); + node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); std::string chain_id_str = node_rpc_client->get_chain_id(); chain_id = chain_id_type(chain_id_str); -- 2.45.2 From d2c1711f7bfdd95704e25ff532072667e42398f5 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 8 Sep 2021 16:42:34 +0200 Subject: [PATCH 31/57] New sync check on SON processing --- .../peerplays_sidechain/peerplays_sidechain_plugin.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index ca258667..02a046fc 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -448,9 +448,15 @@ void peerplays_sidechain_plugin_impl::son_processing() { return; } + //fc::time_point now_fine = fc::time_point::now(); + //fc::time_point_sec now = now_fine + fc::microseconds(500000); + //if (plugin.database().get_slot_time(1) < now) { + // return; // Not synced + //} + fc::time_point now_fine = fc::time_point::now(); - fc::time_point_sec now = now_fine + fc::microseconds(500000); - if (plugin.database().get_slot_time(1) < now) { + fc::time_point_sec now = now_fine - fc::milliseconds(3000); + if (plugin.database().head_block_time() < now) { return; // Not synced } -- 2.45.2 From d0e59a1c60009892f1ee36e5f16146167aecca04 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Sat, 11 Sep 2021 05:26:24 +0200 Subject: [PATCH 32/57] Reset sidechain counters + tests --- libraries/chain/db_maint.cpp | 11 +++++------ tests/tests/son_operations_tests.cpp | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index ed87d5c3..fc931113 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -248,9 +248,6 @@ void database::pay_sons() for (const auto &ts : s.txs_signed) { _s.txs_signed.at(ts.first) = 0; } - for (const auto &str : s.sidechain_txs_reported) { - _s.sidechain_txs_reported.at(str.first) = 0; - } }); } }); @@ -280,11 +277,13 @@ void database::update_son_metrics(const vector& curr_active_sons) bool is_active_son = (std::find(current_sons.begin(), current_sons.end(), son.id) != current_sons.end()); modify( stats, [&]( son_statistics_object& _stats ) { + if(is_active_son) { + _stats.total_voted_time = _stats.total_voted_time + get_global_properties().parameters.maintenance_interval; + } _stats.total_downtime += _stats.current_interval_downtime; _stats.current_interval_downtime = 0; - if(is_active_son) - { - _stats.total_voted_time = _stats.total_voted_time + get_global_properties().parameters.maintenance_interval; + for (const auto &str : _stats.sidechain_txs_reported) { + _stats.sidechain_txs_reported.at(str.first) = 0; } }); } diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index f66cbd48..1e3bb7e4 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -496,6 +496,12 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) _s.total_txs_signed[sidechain_type::bitcoin] = 2; _s.total_txs_signed[sidechain_type::hive] = 4; + + _s.sidechain_txs_reported[sidechain_type::bitcoin] = 4; + _s.sidechain_txs_reported[sidechain_type::hive] = 8; + + _s.total_sidechain_txs_reported[sidechain_type::bitcoin] = 4; + _s.total_sidechain_txs_reported[sidechain_type::hive] = 8; }); // Modify the transaction signed statistics of Bob's SON db.modify( *son_stats_obj2, [&]( son_statistics_object& _s) @@ -505,6 +511,12 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) _s.total_txs_signed[sidechain_type::bitcoin] = 3; _s.total_txs_signed[sidechain_type::hive] = 6; + + _s.sidechain_txs_reported[sidechain_type::bitcoin] = 6; + _s.sidechain_txs_reported[sidechain_type::hive] = 12; + + _s.total_sidechain_txs_reported[sidechain_type::bitcoin] = 6; + _s.total_sidechain_txs_reported[sidechain_type::hive] = 12; }); // Note the balances before the maintenance @@ -518,11 +530,19 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed.at(sidechain_type::hive), 0); BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed.at(sidechain_type::bitcoin), 0); BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed.at(sidechain_type::hive), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->sidechain_txs_reported.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->sidechain_txs_reported.at(sidechain_type::hive), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->sidechain_txs_reported.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->sidechain_txs_reported.at(sidechain_type::hive), 0); BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed.at(sidechain_type::bitcoin), 2); BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed.at(sidechain_type::hive), 4); BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed.at(sidechain_type::bitcoin), 3); BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed.at(sidechain_type::hive), 6); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_sidechain_txs_reported.at(sidechain_type::bitcoin), 4); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_sidechain_txs_reported.at(sidechain_type::hive), 8); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_sidechain_txs_reported.at(sidechain_type::bitcoin), 6); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_sidechain_txs_reported.at(sidechain_type::hive), 12); // Check that Alice and Bob are paid for signing the transactions in the previous day/cycle BOOST_REQUIRE_EQUAL(db.get_balance(obj1->son_account, asset_id_type()).amount.value, 80+obj1_balance); BOOST_REQUIRE_EQUAL(db.get_balance(obj2->son_account, asset_id_type()).amount.value, 120+obj2_balance); -- 2.45.2 From 2a4a4b8dc5c3cca395805030792addb23c7d77ee Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 22 Sep 2021 16:01:43 +0200 Subject: [PATCH 33/57] Enable SON Hive withdrawal without registering sidechain address --- libraries/chain/protocol/memo.cpp | 4 ++-- .../sidechain_net_handler.cpp | 24 +++++++++++++++---- .../sidechain_net_handler_hive.cpp | 1 + 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libraries/chain/protocol/memo.cpp b/libraries/chain/protocol/memo.cpp index afa0b486..1602ae77 100644 --- a/libraries/chain/protocol/memo.cpp +++ b/libraries/chain/protocol/memo.cpp @@ -30,7 +30,7 @@ namespace graphene { namespace chain { void memo_data::set_message(const fc::ecc::private_key& priv, const fc::ecc::public_key& pub, const string& msg, uint64_t custom_nonce) { - if( priv != fc::ecc::private_key() && public_key_type(pub) != public_key_type() ) + if( priv != fc::ecc::private_key() && pub.valid() ) { from = priv.get_public_key(); to = pub; @@ -57,7 +57,7 @@ void memo_data::set_message(const fc::ecc::private_key& priv, const fc::ecc::pub string memo_data::get_message(const fc::ecc::private_key& priv, const fc::ecc::public_key& pub)const { - if( from != public_key_type() ) + if( from != public_key_type() && pub.valid() ) { auto secret = priv.get_shared_secret(pub); auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str()); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 7d3314ab..3cea27a3 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include #include @@ -223,10 +225,14 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ // Withdrawal request if (withdraw_condition) { + std::string withdraw_address = ""; const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain, time_point_sec::maximum())); - if (addr_itr == sidechain_addresses_idx.end()) - return; + if (addr_itr != sidechain_addresses_idx.end()) { + withdraw_address = addr_itr->withdraw_address; + } else { + withdraw_address = sed.sidechain_from; + } std::string withdraw_currency = ""; price withdraw_currency_price = {}; @@ -260,7 +266,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ op.peerplays_from = sed.peerplays_from; op.peerplays_asset = sed.peerplays_asset; op.withdraw_sidechain = sidechain; - op.withdraw_address = addr_itr->withdraw_address; + op.withdraw_address = withdraw_address; op.withdraw_currency = withdraw_currency; op.withdraw_amount = sed.peerplays_asset.amount * withdraw_currency_price.quote.amount / withdraw_currency_price.base.amount; @@ -636,6 +642,16 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) { continue; } + std::string sidechain_from = account_id_to_string(transfer_op.from); + std::string memo = ""; + if (transfer_op.memo) { + memo = transfer_op.memo->get_message(fc::ecc::private_key(), public_key_type()); + boost::trim(memo); + if (!memo.empty()) { + sidechain_from = memo; + } + } + std::stringstream ss; ss << "peerplays" << "-" << trx.id().str() << "-" << operation_index; @@ -647,7 +663,7 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) { sed.sidechain = sidechain_type::peerplays; sed.sidechain_uid = sidechain_uid; sed.sidechain_transaction_id = trx.id().str(); - sed.sidechain_from = account_id_to_string(transfer_op.from); + sed.sidechain_from = sidechain_from; sed.sidechain_to = account_id_to_string(transfer_op.to); sed.sidechain_currency = asset_id_to_string(transfer_op.amount.asset_id); sed.sidechain_amount = transfer_op.amount.amount; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 64a1772c..b1945588 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- 2.45.2 From 9b3c84c2bdd0f251140b08cd0a0683e1abafdd5e Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 5 Oct 2021 19:34:26 +0200 Subject: [PATCH 34/57] Ensure bitcoin primary wallet data is valid before creating primary wallet transaction --- .../sidechain_net_handler_bitcoin.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 215071eb..bc50cee7 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1576,7 +1576,17 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const s std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address) { - std::stringstream prev_sw_ss(prev_swo.addresses.find(sidechain_type::bitcoin)->second); + const auto &address_data = prev_swo.addresses.find(sidechain_type::bitcoin); + if (address_data == prev_swo.addresses.end()) { + return ""; + } + + std::string s = address_data->second; + if (s.empty()) { + return ""; + } + + std::stringstream prev_sw_ss(s); boost::property_tree::ptree prev_sw_pt; boost::property_tree::read_json(prev_sw_ss, prev_sw_pt); std::string prev_pw_address = prev_sw_pt.get("address"); -- 2.45.2 From de9ee9fc76de587b1fddd05e10f3dbeddcc753a3 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 20 Oct 2021 14:31:03 +0200 Subject: [PATCH 35/57] cURL based HTTP/HTTPS RPC client for Hive --- .../peerplays_sidechain/CMakeLists.txt | 2 +- .../peerplays_sidechain/common/rpc_client.cpp | 80 ++++++++++++++++--- .../peerplays_sidechain/common/rpc_client.hpp | 8 +- .../sidechain_net_handler_hive.cpp | 16 ++-- 4 files changed, 87 insertions(+), 19 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 48dd44f1..bb74df29 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -43,7 +43,7 @@ endif() unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS) unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE) -target_link_libraries( peerplays_sidechain PRIVATE graphene_plugin zmq ) +target_link_libraries( peerplays_sidechain PRIVATE curl graphene_plugin zmq ) target_include_directories( peerplays_sidechain PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index cb7c5251..cad283a7 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -1,13 +1,16 @@ #include #include +#include #include #include +#include + #include #include -#include +//#include namespace graphene { namespace peerplays_sidechain { @@ -99,19 +102,78 @@ std::string rpc_client::send_post_request(std::string method, std::string params return ""; } -fc::http::reply 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), port)); +//fc::http::reply 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), port)); +// +// std::string url = "http://" + ip + ":" + std::to_string(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; +//} - std::string url = "http://" + ip + ":" + std::to_string(port); +static size_t write_callback(char *ptr, size_t size, size_t nmemb, rpc_reply *reply) { + size_t retval = 0; + if (reply != nullptr) { + reply->body.append(ptr, size * nmemb); + retval = size * nmemb; + } + return retval; +} - //if (wallet.length() > 0) { - // url = url + "/wallet/" + wallet; - //} +rpc_reply rpc_client::send_post_request(std::string body, bool show_log) { - fc::http::reply reply = conn.request("POST", url, body, fc::http::headers{authorization}); + struct curl_slist *headers = nullptr; + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charset: utf-8"); + + CURL *curl = curl_easy_init(); + if (ip.find("https://", 0) != 0) { + curl_easy_setopt(curl, CURLOPT_URL, ip.c_str()); + curl_easy_setopt(curl, CURLOPT_PORT, port); + } else { + std::string full_address = ip + ":" + std::to_string(port); + curl_easy_setopt(curl, CURLOPT_URL, full_address.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); + } + if (!user.empty()) { + curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str()); + curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str()); + } + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str()); + + //curl_easy_setopt(curl, CURLOPT_VERBOSE, true); + + rpc_reply reply; + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reply); + + curl_easy_perform(curl); + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &reply.status); + + curl_easy_cleanup(curl); + curl_slist_free_all(headers); if (show_log) { + std::string url = ip + ":" + std::to_string(port); ilog("### Request URL: ${url}", ("url", url)); ilog("### Request: ${body}", ("body", body)); std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index c3edd145..f61bdb3f 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -7,6 +7,11 @@ namespace graphene { namespace peerplays_sidechain { +struct rpc_reply { + uint16_t status; + std::string body; +}; + class rpc_client { public: rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls); @@ -27,7 +32,8 @@ protected: fc::http::header authorization; private: - fc::http::reply send_post_request(std::string body, bool show_log); + //fc::http::reply send_post_request(std::string body, bool show_log); + rpc_reply send_post_request(std::string body, bool show_log); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index b1945588..e1a5c329 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -35,7 +35,7 @@ hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std: } std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { - std::string params = "{ \"id\": \"" + transaction_id + "\" }"; + std::string params = "{ \"id\": \"" + transaction_id + "\", \"include_reversible\": \"true\" }"; return send_post_request("account_history_api.get_transaction", params, debug_rpc_calls); } @@ -145,13 +145,13 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi } } - fc::http::connection conn; - try { - conn.connect_to(fc::ip::endpoint(fc::ip::address(node_ip), node_rpc_port)); - } catch (fc::exception &e) { - elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); - FC_ASSERT(false); - } + //fc::http::connection conn; + //try { + // conn.connect_to(fc::ip::endpoint(fc::ip::address(node_ip), node_rpc_port)); + //} catch (fc::exception &e) { + // elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); + // FC_ASSERT(false); + //} node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); -- 2.45.2 From ae079b35640649046b0401568285df10178f151f Mon Sep 17 00:00:00 2001 From: serkixenos Date: Sat, 23 Oct 2021 00:58:21 +0200 Subject: [PATCH 36/57] Refactor Hive transaction inspection, eliminate redundant RPC calls --- .../sidechain_net_handler_hive.cpp | 117 ++++++++++-------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index e1a5c329..5597c06a 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -35,7 +35,7 @@ hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std: } std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { - std::string params = "{ \"id\": \"" + transaction_id + "\", \"include_reversible\": \"true\" }"; + std::string params = "{ \"id\": \"" + transaction_id + "\" }"; return send_post_request("account_history_api.get_transaction", params, debug_rpc_calls); } @@ -161,9 +161,11 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi std::string is_test_net = node_rpc_client->get_is_test_net(); network_type = is_test_net.compare("true") == 0 ? hive::network::testnet : hive::network::mainnet; if (network_type == hive::network::mainnet) { + ilog("Running on Hive mainnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str)); hive::asset::hbd_symbol_ser = HBD_SYMBOL_SER; hive::asset::hive_symbol_ser = HIVE_SYMBOL_SER; } else { + ilog("Running on Hive testnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str)); hive::asset::hbd_symbol_ser = TBD_SYMBOL_SER; hive::asset::hive_symbol_ser = TESTS_SYMBOL_SER; } @@ -817,7 +819,6 @@ void sidechain_net_handler_hive::hive_listener_loop() { schedule_hive_listener(); std::string reply = node_rpc_client->database_api_get_dynamic_global_properties(); - if (!reply.empty()) { std::stringstream ss(reply); boost::property_tree::ptree json; @@ -831,6 +832,16 @@ void sidechain_net_handler_hive::hive_listener_loop() { } } } + + //std::string reply = node_rpc_client->get_last_irreversible_block_num(); + //if (!reply.empty()) { + // uint64_t last_irreversible_block = std::stoul(reply); + // if (last_irreversible_block != last_block_received) { + // std::string event_data = std::to_string(last_irreversible_block); + // handle_event(event_data); + // last_block_received = last_irreversible_block; + // } + //} } void sidechain_net_handler_hive::handle_event(const std::string &event_data) { @@ -840,28 +851,25 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { boost::property_tree::ptree block_json; boost::property_tree::read_json(ss, block_json); - for (const auto &tx_ids_child : block_json.get_child("result.block.transaction_ids")) { - const auto &transaction_id = tx_ids_child.second.get_value(); + size_t tx_idx = -1; + for (const auto &tx_ids_child : block_json.get_child("result.block.transactions")) { + boost::property_tree::ptree tx = tx_ids_child.second; + tx_idx = tx_idx + 1; - std::string tx_str = node_rpc_client->account_history_api_get_transaction(transaction_id); - if (tx_str != "") { + size_t op_idx = -1; + for (const auto &ops : tx.get_child("operations")) { + const auto &op = ops.second; + op_idx = op_idx + 1; - std::stringstream ss_tx(tx_str); - boost::property_tree::ptree tx; - boost::property_tree::read_json(ss_tx, tx); + std::string operation_type = op.get("type"); - size_t op_idx = -1; - for (const auto &ops : tx.get_child("result.operations")) { - const auto &op = ops.second; - op_idx = op_idx + 1; + if (operation_type == "transfer_operation") { + const auto &op_value = op.get_child("value"); - std::string operation_type = op.get("type"); + std::string from = op_value.get("from"); + std::string to = op_value.get("to"); - if (operation_type == "transfer_operation") { - const auto &op_value = op.get_child("value"); - - std::string from = op_value.get("from"); - std::string to = op_value.get("to"); + if (to == "son-account") { const auto &amount_child = op_value.get_child("amount"); @@ -885,42 +893,47 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) { from = memo; } - if (to == "son-account") { - const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum())); - account_id_type accn = account_id_type(); - if (addr_itr == sidechain_addresses_idx.end()) { - const auto &account_idx = database.get_index_type().indices().get(); - const auto &account_itr = account_idx.find(from); - if (account_itr == account_idx.end()) { - continue; - } else { - accn = account_itr->id; - } + const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum())); + account_id_type accn = account_id_type(); + if (addr_itr == sidechain_addresses_idx.end()) { + const auto &account_idx = database.get_index_type().indices().get(); + const auto &account_itr = account_idx.find(from); + if (account_itr == account_idx.end()) { + continue; } else { - accn = addr_itr->sidechain_address_account; + accn = account_itr->id; } - - std::stringstream ss; - ss << "hive" - << "-" << transaction_id << "-" << op_idx; - 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; - sed.sidechain_uid = sidechain_uid; - sed.sidechain_transaction_id = transaction_id; - sed.sidechain_from = from; - sed.sidechain_to = to; - sed.sidechain_currency = sidechain_currency; - sed.sidechain_amount = amount; - sed.peerplays_from = accn; - sed.peerplays_to = database.get_global_properties().parameters.son_account(); - sed.peerplays_asset = asset(sed.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount); - sidechain_event_data_received(sed); + } else { + accn = addr_itr->sidechain_address_account; } + + std::vector transaction_ids; + for (const auto &tx_ids_child : block_json.get_child("result.block.transaction_ids")) { + const auto &transaction_id = tx_ids_child.second.get_value(); + transaction_ids.push_back(transaction_id); + } + std::string transaction_id = transaction_ids.at(tx_idx); + + std::stringstream ss; + ss << "hive" + << "-" << transaction_id << "-" << op_idx; + 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; + sed.sidechain_uid = sidechain_uid; + sed.sidechain_transaction_id = transaction_id; + sed.sidechain_from = from; + sed.sidechain_to = to; + sed.sidechain_currency = sidechain_currency; + sed.sidechain_amount = amount; + sed.peerplays_from = accn; + sed.peerplays_to = database.get_global_properties().parameters.son_account(); + sed.peerplays_asset = asset(sed.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount); + sidechain_event_data_received(sed); } } } -- 2.45.2 From cadd22fdb8975471f927cce9c09850a3db4c53ad Mon Sep 17 00:00:00 2001 From: serkixenos Date: Mon, 25 Oct 2021 15:18:28 +0000 Subject: [PATCH 37/57] [SON for Hive] - Implement HTTPS RPC client --- .gitignore | 1 + clang-format.sh | 4 + .../peerplays_sidechain/common/rpc_client.cpp | 425 +++++++++++++++--- .../plugins/peerplays_sidechain/format.sh | 2 + .../sidechain_net_handler_hive.cpp | 63 ++- 5 files changed, 424 insertions(+), 71 deletions(-) create mode 100755 clang-format.sh create mode 100755 libraries/plugins/peerplays_sidechain/format.sh diff --git a/.gitignore b/.gitignore index 39b23163..1a84b559 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ data CMakeDoxyfile.in build +build__* libraries/utilities/git_revision.cpp diff --git a/clang-format.sh b/clang-format.sh new file mode 100755 index 00000000..6ab95eb9 --- /dev/null +++ b/clang-format.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +find ./libraries/plugins/peerplays_sidechain -regex ".*[c|h]pp" | xargs clang-format -i + diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index cad283a7..1db7c889 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -3,6 +3,10 @@ #include #include +#include +#include +#include + #include #include @@ -10,7 +14,317 @@ #include #include -//#include +#include + +#include +#include + +namespace graphene { namespace peerplays_sidechain { + +struct http_request { + + std::string method; // ex: "POST" + std::string path; // ex: "/" + std::string headers; + std::string body; + std::string content_type; // ex: "application/json" + + http_request() { + } + + http_request(const std::string &method_, const std::string &path_, const std::string &headers_, const std::string &body_, const std::string &content_type_) : + method(method_), + path(path_), + headers(headers_), + body(body_), + content_type(content_type_) { + } + + http_request(const std::string &method_, const std::string &path_, const std::string &headers_, const std::string &body_ = std::string()) : + method(method_), + path(path_), + headers(headers_), + body(body_), + content_type("application/json") { + } + + void clear() { + method.clear(); + path.clear(); + headers.clear(); + body.clear(); + content_type.clear(); + } +}; + +struct http_response { + + uint16_t status_code; + std::string body; + + void clear() { + status_code = 0; + body = decltype(body)(); + } +}; + +class https_call { +public: + https_call(const std::string &host, uint16_t port = 0) : + m_host(host), + m_port(port) { + } + + const std::string &host() const { + return m_host; + } + + uint16_t port() const { + return m_port; + } + + uint32_t response_size_limit_bytes() const { + return 1024 * 1024; + } + + bool exec(const http_request &request, http_response *response); + +private: + std::string m_host; + uint16_t m_port; +}; + +namespace detail { + +static const char cr = 0x0D; +static const char lf = 0x0A; +static const char *crlf = "\x0D\x0A"; +static const char *crlfcrlf = "\x0D\x0A\x0D\x0A"; + +using namespace boost::asio; + +class https_call_impl { +public: + https_call_impl(const https_call &call, const http_request &request, http_response &response) : + m_call(call), + m_request(request), + m_response(response), + m_service(), + m_context(ssl::context::tlsv12_client), + m_socket(m_service, m_context), + m_endpoint(), + m_response_buf(call.response_size_limit_bytes()), + m_content_length(0) { + m_context.set_default_verify_paths(); + } + + void exec() { + resolve(); + connect(); + send_request(); + process_response(); + } + +private: + const https_call &m_call; + const http_request &m_request; + http_response &m_response; + + io_service m_service; + ssl::context m_context; + ssl::stream m_socket; + ip::tcp::endpoint m_endpoint; + streambuf m_response_buf; + uint32_t m_content_length; + + void resolve() { + + // resolve TCP endpoint for host name + + ip::tcp::resolver resolver(m_service); + auto query = ip::tcp::resolver::query(m_call.host(), "https"); + auto iter = resolver.resolve(query); + m_endpoint = *iter; + + if (m_call.port() != 0) // if port was specified + m_endpoint.port(m_call.port()); // force set port + } + + void connect() { + + // TCP connect + + m_socket.lowest_layer().connect(m_endpoint); + + // SSL connect + + m_socket.set_verify_mode(ssl::verify_peer); + m_socket.handshake(ssl::stream_base::client); + } + + void send_request() { + + streambuf request_buf; + std::ostream stream(&request_buf); + + // start string: HTTP/1.0 + + stream << m_request.method << " " << m_request.path << " HTTP/1.0" << crlf; + + // host + + stream << "Host: " << m_call.host(); + + if (m_call.port() != 0) { + //ASSERT(m_Endpoint.port() == m_Call.port()); + stream << ":" << m_call.port(); + } + + stream << crlf; + + // content + + if (!m_request.body.empty()) { + stream << "Content-Type: " << m_request.content_type << crlf; + stream << "Content-Length: " << m_request.body.size() << crlf; + } + + // additional headers + + const auto &h = m_request.headers; + + if (!h.empty()) { + if (h.size() < 2) { + FC_THROW("invalid headers data"); + } + stream << h; + // ensure headers finished correctly + if ((h.substr(h.size() - 2) != crlf)) + stream << crlf; + } + + // other + + stream << "Accept: *\x2F*" << crlf; + stream << "Connection: close" << crlf; + + // end + + stream << crlf; + + // content + + if (!m_request.body.empty()) + stream << m_request.body; + + // send + + write(m_socket, request_buf); + } + + void process_headers() { + + std::istream stream(&m_response_buf); + + std::string http_version; + stream >> http_version; + stream >> m_response.status_code; + + if (!stream || http_version.substr(0, 5) != "HTTP/") { + FC_THROW("invalid response data"); + } + + // read/skip headers + + for (;;) { + std::string header; + if (!std::getline(stream, header, lf) || (header.size() == 1 && header[0] == cr)) + break; + if (m_content_length) // if content length is already known + continue; // continue skipping headers + auto pos = header.find(':'); + if (pos == std::string::npos) + continue; + auto name = header.substr(0, pos); + boost::algorithm::trim(name); + boost::algorithm::to_lower(name); + if (name != "content-length") + continue; + auto value = header.substr(pos + 1); + boost::algorithm::trim(value); + m_content_length = std::stol(value); + } + } + + void process_response() { + + auto &socket = m_socket; + auto &buf = m_response_buf; + auto &content_length = m_content_length; + auto &body = m_response.body; + + read_until(socket, buf, crlfcrlf); + + process_headers(); + + // check content length + + if (content_length < 2) { // minimum content is "{}" + FC_THROW("invalid response body (too short)"); + } + + if (content_length > m_call.response_size_limit_bytes()) { + FC_THROW("response body size limit exceeded"); + } + + // read body + + auto avail = buf.size(); // size of body data already stored in the buffer + + if (avail > content_length) { + FC_THROW("invalid response body (content length mismatch)"); + } + + body.resize(content_length); + + if (avail) { + // copy already existing data + if (avail != buf.sgetn(&body[0], avail)) { + FC_THROW("stream read failed"); + } + } + + auto rest = content_length - avail; // size of remaining part of response body + + boost::system::error_code error_code; + + read(socket, buffer(&body[avail], rest), error_code); // read remaining part + + socket.shutdown(error_code); + } +}; + +} // namespace detail + +bool https_call::exec(const http_request &request, http_response *response) { + + // ASSERT(response); + auto &resp = *response; + + detail::https_call_impl impl(*this, request, resp); + + try { + resp.clear(); + impl.exec(); + } catch (...) { + resp.clear(); + return false; + } + + return true; +} + +}} // namespace graphene::peerplays_sidechain namespace graphene { namespace peerplays_sidechain { @@ -102,75 +416,60 @@ std::string rpc_client::send_post_request(std::string method, std::string params return ""; } -//fc::http::reply 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), port)); -// -// std::string url = "http://" + ip + ":" + std::to_string(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; -//} - -static size_t write_callback(char *ptr, size_t size, size_t nmemb, rpc_reply *reply) { - size_t retval = 0; - if (reply != nullptr) { - reply->body.append(ptr, size * nmemb); - retval = size * nmemb; - } - return retval; -} - rpc_reply rpc_client::send_post_request(std::string body, bool show_log) { - struct curl_slist *headers = nullptr; - headers = curl_slist_append(headers, "Accept: application/json"); - headers = curl_slist_append(headers, "Content-Type: application/json"); - headers = curl_slist_append(headers, "charset: utf-8"); - - CURL *curl = curl_easy_init(); - if (ip.find("https://", 0) != 0) { - curl_easy_setopt(curl, CURLOPT_URL, ip.c_str()); - curl_easy_setopt(curl, CURLOPT_PORT, port); - } else { - std::string full_address = ip + ":" + std::to_string(port); - curl_easy_setopt(curl, CURLOPT_URL, full_address.c_str()); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); - } - if (!user.empty()) { - curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str()); - curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str()); - } - - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str()); - - //curl_easy_setopt(curl, CURLOPT_VERBOSE, true); - rpc_reply reply; + auto start = ip.substr(0, 6); + boost::algorithm::to_lower(start); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reply); + if (start == "https:") { - curl_easy_perform(curl); + auto host = ip.substr(8); // skip "https://" - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &reply.status); + https_call call(host, port); + http_request request("POST", "/", authorization.key + ":" + authorization.val, body); + http_response response; - curl_easy_cleanup(curl); - curl_slist_free_all(headers); + if (call.exec(request, &response)) { + reply.status = response.status_code; + reply.body.resize(response.body.size()); + memcpy(&reply.body[0], &response.body[0], response.body.size()); + } + + } else { + + std::string host; + + if (start == "http:/") + host = ip.substr(7); // skip "http://" + else + host = ip; + + std::string url = "http://" + host + ":" + std::to_string(port); + fc::ip::address addr; + + try { + addr = fc::ip::address(host); + } catch (...) { + return reply; + } + + try { + + fc::http::connection conn; + conn.connect_to(fc::ip::endpoint(addr, port)); + + //if (wallet.length() > 0) { + // url = url + "/wallet/" + wallet; + //} + + auto r = conn.request("POST", url, body, fc::http::headers{authorization}); + reply.status = r.status; + reply.body.assign(r.body.begin(), r.body.end()); + + } catch (...) { + } + } if (show_log) { std::string url = ip + ":" + std::to_string(port); diff --git a/libraries/plugins/peerplays_sidechain/format.sh b/libraries/plugins/peerplays_sidechain/format.sh new file mode 100755 index 00000000..7b739d7f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/format.sh @@ -0,0 +1,2 @@ +#!/bin/bash +find . -regex ".*[c|h]pp" | xargs clang-format -i diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 5597c06a..2db3063d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -28,6 +28,35 @@ #include #include +#include + +namespace graphene { namespace peerplays_sidechain { + +std::string resolve_host_addr(const std::string &host_name) { + using namespace boost::asio; + io_service service; + ip::tcp::resolver resolver(service); + auto query = ip::tcp::resolver::query(host_name, std::string()); + auto iter = resolver.resolve(query); + auto endpoint = *iter; + auto addr = ((ip::tcp::endpoint)endpoint).address(); + return addr.to_string(); +} + +std::string strip_proto_name(const std::string &url, std::string *schema) { + auto index = url.find("://"); + if (index == std::string::npos) { + if (schema) + schema->clear(); + return url; + } + if (schema) + schema->assign(&url[0], &url[index + 3]); + return url.substr(index + 3); +} + +}} // namespace graphene::peerplays_sidechain + namespace graphene { namespace peerplays_sidechain { hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : @@ -145,15 +174,33 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi } } - //fc::http::connection conn; - //try { - // conn.connect_to(fc::ip::endpoint(fc::ip::address(node_ip), node_rpc_port)); - //} catch (fc::exception &e) { - // elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); - // FC_ASSERT(false); - //} + std::string schema; + auto host = strip_proto_name(node_ip, &schema); - node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); + try { + fc::ip::address ip_addr; + try { + // IP address assumed + ip_addr = fc::ip::address(host); + } catch (...) { + try { + // host name assumed + host = resolve_host_addr(host); + ip_addr = fc::ip::address(host); + } catch (...) { + elog("Failed to resolve Hive node address ${ip}", ("ip", node_ip)); + FC_ASSERT(false); + } + } + // try to connect to TCP endpoint + fc::http::connection conn; + conn.connect_to(fc::ip::endpoint(ip_addr, node_rpc_port)); + } catch (fc::exception &e) { + elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); + FC_ASSERT(false); + } + + node_rpc_client = new hive_node_rpc_client(schema + host, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); std::string chain_id_str = node_rpc_client->get_chain_id(); chain_id = chain_id_type(chain_id_str); -- 2.45.2 From 524f409f81a48915b9afa5a198838086202e0d2e Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 27 Oct 2021 02:24:06 +0200 Subject: [PATCH 38/57] Add timestamp field to sidechain transaction object --- .../include/graphene/chain/sidechain_transaction_object.hpp | 2 ++ libraries/chain/sidechain_transaction_evaluator.cpp | 1 + libraries/plugins/peerplays_sidechain/format.sh | 2 -- 3 files changed, 3 insertions(+), 2 deletions(-) delete mode 100755 libraries/plugins/peerplays_sidechain/format.sh diff --git a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp index da39f636..30a0dd5e 100644 --- a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp @@ -26,6 +26,7 @@ namespace graphene { namespace chain { static const uint8_t space_id = protocol_ids; static const uint8_t type_id = sidechain_transaction_object_type; + time_point_sec timestamp; sidechain_type sidechain = sidechain_type::unknown; object_id_type object_id; std::string transaction; @@ -70,6 +71,7 @@ FC_REFLECT_ENUM( graphene::chain::sidechain_transaction_status, (settled) ) FC_REFLECT_DERIVED( graphene::chain::sidechain_transaction_object, (graphene::db::object ), + (timestamp) (sidechain) (object_id) (transaction) diff --git a/libraries/chain/sidechain_transaction_evaluator.cpp b/libraries/chain/sidechain_transaction_evaluator.cpp index a56216fe..ba256199 100644 --- a/libraries/chain/sidechain_transaction_evaluator.cpp +++ b/libraries/chain/sidechain_transaction_evaluator.cpp @@ -28,6 +28,7 @@ void_result sidechain_transaction_create_evaluator::do_evaluate(const sidechain_ object_id_type sidechain_transaction_create_evaluator::do_apply(const sidechain_transaction_create_operation &op) { try { const auto &new_sidechain_transaction_object = db().create([&](sidechain_transaction_object &sto) { + sto.timestamp = db().head_block_time(); sto.sidechain = op.sidechain; sto.object_id = op.object_id; sto.transaction = op.transaction; diff --git a/libraries/plugins/peerplays_sidechain/format.sh b/libraries/plugins/peerplays_sidechain/format.sh deleted file mode 100755 index 7b739d7f..00000000 --- a/libraries/plugins/peerplays_sidechain/format.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -find . -regex ".*[c|h]pp" | xargs clang-format -i -- 2.45.2 From e964ac2f0fbf6223bf9fe111225364748d76b286 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Fri, 29 Oct 2021 02:55:37 +0200 Subject: [PATCH 39/57] Set valid Hive public key prefix for both mainnet and testnet --- libraries/plugins/peerplays_sidechain/hive/types.cpp | 6 ++---- .../include/graphene/peerplays_sidechain/hive/types.hpp | 6 ++++++ .../peerplays_sidechain/sidechain_net_handler_hive.cpp | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/hive/types.cpp b/libraries/plugins/peerplays_sidechain/hive/types.cpp index c2436701..7a5506e7 100644 --- a/libraries/plugins/peerplays_sidechain/hive/types.cpp +++ b/libraries/plugins/peerplays_sidechain/hive/types.cpp @@ -7,7 +7,7 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { -#define ADDRESS_PREFIX "TST" +std::string public_key_type::prefix = KEY_PREFIX_STM; public_key_type::public_key_type() : key_data(){}; @@ -19,8 +19,6 @@ public_key_type::public_key_type(const fc::ecc::public_key &pubkey) : key_data(pubkey){}; public_key_type::public_key_type(const std::string &base58str) { - std::string prefix(ADDRESS_PREFIX); - const size_t prefix_len = prefix.size(); FC_ASSERT(base58str.size() > prefix_len); FC_ASSERT(base58str.substr(0, prefix_len) == prefix, "", ("base58str", base58str)); @@ -43,7 +41,7 @@ public_key_type::operator std::string() const { k.data = key_data; k.check = fc::ripemd160::hash(k.data.data, k.data.size())._hash[0]; auto data = fc::raw::pack(k); - return ADDRESS_PREFIX + fc::to_base58(data.data(), data.size()); + return prefix + fc::to_base58(data.data(), data.size()); } bool operator==(const public_key_type &p1, const fc::ecc::public_key &p2) { diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp index 85e16a8c..f5b986e4 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -5,6 +5,9 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { +#define KEY_PREFIX_STM "STM" +#define KEY_PREFIX_TST "TST" + enum network { mainnet, testnet @@ -30,6 +33,9 @@ typedef fc::safe share_type; //typedef fixed_string<32> custom_id_type; struct public_key_type { + + static std::string prefix; + struct binary_key { binary_key() { } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 2db3063d..9662e3ce 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -211,10 +211,12 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi ilog("Running on Hive mainnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str)); hive::asset::hbd_symbol_ser = HBD_SYMBOL_SER; hive::asset::hive_symbol_ser = HIVE_SYMBOL_SER; + hive::public_key_type::prefix = KEY_PREFIX_STM; } else { ilog("Running on Hive testnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str)); hive::asset::hbd_symbol_ser = TBD_SYMBOL_SER; hive::asset::hive_symbol_ser = TESTS_SYMBOL_SER; + hive::public_key_type::prefix = KEY_PREFIX_TST; } last_block_received = 0; -- 2.45.2 From daa0d6c06b462dc217b48f9c660837b899017d87 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Sun, 31 Oct 2021 02:02:10 +0100 Subject: [PATCH 40/57] Verify that SON has non empty Hive sidechain config --- libraries/chain/son_object.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/chain/son_object.cpp b/libraries/chain/son_object.cpp index bf54c833..e782a3e9 100644 --- a/libraries/chain/son_object.cpp +++ b/libraries/chain/son_object.cpp @@ -10,6 +10,8 @@ namespace graphene { namespace chain { return ((std::string(signing_key).length() > 0) && (sidechain_public_keys.size() > 0) && (sidechain_public_keys.find( sidechain_type::bitcoin ) != sidechain_public_keys.end()) && - (sidechain_public_keys.at(sidechain_type::bitcoin).length() > 0)); + (sidechain_public_keys.at(sidechain_type::bitcoin).length() > 0) && + (sidechain_public_keys.find( sidechain_type::hive ) != sidechain_public_keys.end()) && + (sidechain_public_keys.at(sidechain_type::hive).length() > 0)); } }} -- 2.45.2 From 958c814710414eb629a47185a1a300b5cc880200 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Sun, 31 Oct 2021 04:36:28 +0100 Subject: [PATCH 41/57] Set Hive transaction expiration to 180 secs --- .../peerplays_sidechain/sidechain_net_handler_hive.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 9662e3ce..a4638387 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -568,7 +568,7 @@ void sidechain_net_handler_hive::process_primary_wallet() { hive::signed_transaction htrx; htrx.set_reference_block(head_block_id); - htrx.set_expiration(head_block_time + fc::seconds(90)); + htrx.set_expiration(head_block_time + fc::seconds(180)); htrx.operations.push_back(auo); @@ -726,7 +726,7 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob hive::signed_transaction htrx; htrx.set_reference_block(head_block_id); - htrx.set_expiration(head_block_time + fc::seconds(90)); + htrx.set_expiration(head_block_time + fc::seconds(180)); htrx.operations.push_back(t_op); -- 2.45.2 From f0b2fceb2825a0c1775154cf34c0520830341612 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Sun, 31 Oct 2021 19:07:39 +0100 Subject: [PATCH 42/57] Fix SON tests --- tests/cli/son.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/cli/son.cpp b/tests/cli/son.cpp index cf4fd8ed..fed39e86 100644 --- a/tests/cli/son.cpp +++ b/tests/cli/son.cpp @@ -121,10 +121,12 @@ BOOST_AUTO_TEST_CASE( create_sons ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); auto son1_obj = con.wallet_api_ptr->get_son("son1account"); @@ -153,6 +155,7 @@ BOOST_AUTO_TEST_CASE( cli_update_son ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; son_test_helper sth(*this); sth.create_son("sonmember", "http://sonmember", sidechain_public_keys); @@ -167,6 +170,7 @@ BOOST_AUTO_TEST_CASE( cli_update_son ) // update SON sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; con.wallet_api_ptr->update_son("sonmember", "http://sonmember_updated", "", sidechain_public_keys, true); son_data = con.wallet_api_ptr->get_son("sonmember"); @@ -197,10 +201,12 @@ BOOST_AUTO_TEST_CASE( son_voting ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); BOOST_TEST_MESSAGE("Voting for SONs"); @@ -292,6 +298,7 @@ BOOST_FIXTURE_TEST_CASE( select_top_fifteen_sons, cli_fixture ) { sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i); + sidechain_public_keys[sidechain_type::hive] = "hive account " + fc::to_pretty_string(i); sth.create_son("sonaccount" + fc::to_pretty_string(i), "http://son" + fc::to_pretty_string(i), sidechain_public_keys, @@ -366,10 +373,12 @@ BOOST_AUTO_TEST_CASE( list_son ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); auto res = con.wallet_api_ptr->list_sons("", 100); @@ -396,10 +405,12 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); BOOST_TEST_MESSAGE("Vote for 2 accounts with update_son_votes"); @@ -555,10 +566,12 @@ BOOST_AUTO_TEST_CASE( related_functions ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); gpo = con.wallet_api_ptr->get_global_properties(); @@ -592,6 +605,7 @@ BOOST_FIXTURE_TEST_CASE( cli_list_active_sons, cli_fixture ) { sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i); + sidechain_public_keys[sidechain_type::hive] = "hive account " + fc::to_pretty_string(i); sth.create_son("sonaccount" + fc::to_pretty_string(i), "http://son" + fc::to_pretty_string(i), sidechain_public_keys, @@ -659,6 +673,7 @@ BOOST_AUTO_TEST_CASE( maintenance_test ) { sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i); + sidechain_public_keys[sidechain_type::hive] = "hive account " + fc::to_pretty_string(i); sth.create_son("sonaccount" + fc::to_pretty_string(i), "http://son" + fc::to_pretty_string(i), sidechain_public_keys, -- 2.45.2 From 9d94503842ac089c83d63fbdb933d902513ca856 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 2 Nov 2021 18:54:05 +0100 Subject: [PATCH 43/57] Asset serializaton from Hive v1.24.8 to Hive 1.25.0 --- .../include/graphene/peerplays_sidechain/hive/asset.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp index d79d2e7d..f0743741 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp @@ -6,12 +6,12 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { #define HBD_NAI "@@000000013" #define HBD_PRECISION 3 -#define HBD_SYMBOL_U64 (uint64_t('H') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define HBD_SYMBOL_U64 (uint64_t('S') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) #define HBD_SYMBOL_SER (uint64_t(3) | (HBD_SYMBOL_U64 << 8)) #define HIVE_NAI "@@000000021" #define HIVE_PRECISION 3 -#define HIVE_SYMBOL_U64 (uint64_t('H') | (uint64_t('I') << 8) | (uint64_t('V') << 16) | (uint64_t('E') << 24)) +#define HIVE_SYMBOL_U64 (uint64_t('S') | (uint64_t('T') << 8) | (uint64_t('E') << 16) | (uint64_t('E') << 24) | (uint64_t('M') << 32)) #define HIVE_SYMBOL_SER (uint64_t(3) | (HIVE_SYMBOL_U64 << 8)) #define TBD_NAI "@@000000013" -- 2.45.2 From aeaab06231f02b34fc3c94b1024c24e0b3103ec3 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 2 Nov 2021 18:55:39 +0100 Subject: [PATCH 44/57] Fallback to cURL based RPC client --- .../peerplays_sidechain/common/rpc_client.cpp | 428 +++--------------- 1 file changed, 64 insertions(+), 364 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 1db7c889..ce4081c2 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -3,10 +3,6 @@ #include #include -#include -#include -#include - #include #include @@ -14,317 +10,6 @@ #include #include -#include - -#include -#include - -namespace graphene { namespace peerplays_sidechain { - -struct http_request { - - std::string method; // ex: "POST" - std::string path; // ex: "/" - std::string headers; - std::string body; - std::string content_type; // ex: "application/json" - - http_request() { - } - - http_request(const std::string &method_, const std::string &path_, const std::string &headers_, const std::string &body_, const std::string &content_type_) : - method(method_), - path(path_), - headers(headers_), - body(body_), - content_type(content_type_) { - } - - http_request(const std::string &method_, const std::string &path_, const std::string &headers_, const std::string &body_ = std::string()) : - method(method_), - path(path_), - headers(headers_), - body(body_), - content_type("application/json") { - } - - void clear() { - method.clear(); - path.clear(); - headers.clear(); - body.clear(); - content_type.clear(); - } -}; - -struct http_response { - - uint16_t status_code; - std::string body; - - void clear() { - status_code = 0; - body = decltype(body)(); - } -}; - -class https_call { -public: - https_call(const std::string &host, uint16_t port = 0) : - m_host(host), - m_port(port) { - } - - const std::string &host() const { - return m_host; - } - - uint16_t port() const { - return m_port; - } - - uint32_t response_size_limit_bytes() const { - return 1024 * 1024; - } - - bool exec(const http_request &request, http_response *response); - -private: - std::string m_host; - uint16_t m_port; -}; - -namespace detail { - -static const char cr = 0x0D; -static const char lf = 0x0A; -static const char *crlf = "\x0D\x0A"; -static const char *crlfcrlf = "\x0D\x0A\x0D\x0A"; - -using namespace boost::asio; - -class https_call_impl { -public: - https_call_impl(const https_call &call, const http_request &request, http_response &response) : - m_call(call), - m_request(request), - m_response(response), - m_service(), - m_context(ssl::context::tlsv12_client), - m_socket(m_service, m_context), - m_endpoint(), - m_response_buf(call.response_size_limit_bytes()), - m_content_length(0) { - m_context.set_default_verify_paths(); - } - - void exec() { - resolve(); - connect(); - send_request(); - process_response(); - } - -private: - const https_call &m_call; - const http_request &m_request; - http_response &m_response; - - io_service m_service; - ssl::context m_context; - ssl::stream m_socket; - ip::tcp::endpoint m_endpoint; - streambuf m_response_buf; - uint32_t m_content_length; - - void resolve() { - - // resolve TCP endpoint for host name - - ip::tcp::resolver resolver(m_service); - auto query = ip::tcp::resolver::query(m_call.host(), "https"); - auto iter = resolver.resolve(query); - m_endpoint = *iter; - - if (m_call.port() != 0) // if port was specified - m_endpoint.port(m_call.port()); // force set port - } - - void connect() { - - // TCP connect - - m_socket.lowest_layer().connect(m_endpoint); - - // SSL connect - - m_socket.set_verify_mode(ssl::verify_peer); - m_socket.handshake(ssl::stream_base::client); - } - - void send_request() { - - streambuf request_buf; - std::ostream stream(&request_buf); - - // start string: HTTP/1.0 - - stream << m_request.method << " " << m_request.path << " HTTP/1.0" << crlf; - - // host - - stream << "Host: " << m_call.host(); - - if (m_call.port() != 0) { - //ASSERT(m_Endpoint.port() == m_Call.port()); - stream << ":" << m_call.port(); - } - - stream << crlf; - - // content - - if (!m_request.body.empty()) { - stream << "Content-Type: " << m_request.content_type << crlf; - stream << "Content-Length: " << m_request.body.size() << crlf; - } - - // additional headers - - const auto &h = m_request.headers; - - if (!h.empty()) { - if (h.size() < 2) { - FC_THROW("invalid headers data"); - } - stream << h; - // ensure headers finished correctly - if ((h.substr(h.size() - 2) != crlf)) - stream << crlf; - } - - // other - - stream << "Accept: *\x2F*" << crlf; - stream << "Connection: close" << crlf; - - // end - - stream << crlf; - - // content - - if (!m_request.body.empty()) - stream << m_request.body; - - // send - - write(m_socket, request_buf); - } - - void process_headers() { - - std::istream stream(&m_response_buf); - - std::string http_version; - stream >> http_version; - stream >> m_response.status_code; - - if (!stream || http_version.substr(0, 5) != "HTTP/") { - FC_THROW("invalid response data"); - } - - // read/skip headers - - for (;;) { - std::string header; - if (!std::getline(stream, header, lf) || (header.size() == 1 && header[0] == cr)) - break; - if (m_content_length) // if content length is already known - continue; // continue skipping headers - auto pos = header.find(':'); - if (pos == std::string::npos) - continue; - auto name = header.substr(0, pos); - boost::algorithm::trim(name); - boost::algorithm::to_lower(name); - if (name != "content-length") - continue; - auto value = header.substr(pos + 1); - boost::algorithm::trim(value); - m_content_length = std::stol(value); - } - } - - void process_response() { - - auto &socket = m_socket; - auto &buf = m_response_buf; - auto &content_length = m_content_length; - auto &body = m_response.body; - - read_until(socket, buf, crlfcrlf); - - process_headers(); - - // check content length - - if (content_length < 2) { // minimum content is "{}" - FC_THROW("invalid response body (too short)"); - } - - if (content_length > m_call.response_size_limit_bytes()) { - FC_THROW("response body size limit exceeded"); - } - - // read body - - auto avail = buf.size(); // size of body data already stored in the buffer - - if (avail > content_length) { - FC_THROW("invalid response body (content length mismatch)"); - } - - body.resize(content_length); - - if (avail) { - // copy already existing data - if (avail != buf.sgetn(&body[0], avail)) { - FC_THROW("stream read failed"); - } - } - - auto rest = content_length - avail; // size of remaining part of response body - - boost::system::error_code error_code; - - read(socket, buffer(&body[avail], rest), error_code); // read remaining part - - socket.shutdown(error_code); - } -}; - -} // namespace detail - -bool https_call::exec(const http_request &request, http_response *response) { - - // ASSERT(response); - auto &resp = *response; - - detail::https_call_impl impl(*this, request, resp); - - try { - resp.clear(); - impl.exec(); - } catch (...) { - resp.clear(); - return false; - } - - return true; -} - -}} // namespace graphene::peerplays_sidechain namespace graphene { namespace peerplays_sidechain { @@ -416,60 +101,75 @@ std::string rpc_client::send_post_request(std::string method, std::string params return ""; } +//fc::http::reply 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), port)); +// +// std::string url = "http://" + ip + ":" + std::to_string(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; +//} + +static size_t write_callback(char *ptr, size_t size, size_t nmemb, rpc_reply *reply) { + size_t retval = 0; + if (reply != nullptr) { + reply->body.append(ptr, size * nmemb); + retval = size * nmemb; + } + return retval; +} + rpc_reply rpc_client::send_post_request(std::string body, bool show_log) { - rpc_reply reply; - auto start = ip.substr(0, 6); - boost::algorithm::to_lower(start); - - if (start == "https:") { - - auto host = ip.substr(8); // skip "https://" - - https_call call(host, port); - http_request request("POST", "/", authorization.key + ":" + authorization.val, body); - http_response response; - - if (call.exec(request, &response)) { - reply.status = response.status_code; - reply.body.resize(response.body.size()); - memcpy(&reply.body[0], &response.body[0], response.body.size()); - } + struct curl_slist *headers = nullptr; + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charset: utf-8"); + CURL *curl = curl_easy_init(); + if (ip.find("https://", 0) != 0) { + curl_easy_setopt(curl, CURLOPT_URL, ip.c_str()); + curl_easy_setopt(curl, CURLOPT_PORT, port); } else { - - std::string host; - - if (start == "http:/") - host = ip.substr(7); // skip "http://" - else - host = ip; - - std::string url = "http://" + host + ":" + std::to_string(port); - fc::ip::address addr; - - try { - addr = fc::ip::address(host); - } catch (...) { - return reply; - } - - try { - - fc::http::connection conn; - conn.connect_to(fc::ip::endpoint(addr, port)); - - //if (wallet.length() > 0) { - // url = url + "/wallet/" + wallet; - //} - - auto r = conn.request("POST", url, body, fc::http::headers{authorization}); - reply.status = r.status; - reply.body.assign(r.body.begin(), r.body.end()); - - } catch (...) { - } + std::string full_address = ip + ":" + std::to_string(port); + curl_easy_setopt(curl, CURLOPT_URL, full_address.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); } + if (!user.empty()) { + curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str()); + curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str()); + } + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str()); + + //curl_easy_setopt(curl, CURLOPT_VERBOSE, true); + + rpc_reply reply; + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reply); + + curl_easy_perform(curl); + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &reply.status); + + curl_easy_cleanup(curl); + curl_slist_free_all(headers); if (show_log) { std::string url = ip + ":" + std::to_string(port); -- 2.45.2 From 88682e9cc15ef7bf3e15fe49accdf1bec5515fd9 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 2 Nov 2021 19:15:53 +0100 Subject: [PATCH 45/57] Refactored Hive connection check --- .../sidechain_net_handler_hive.cpp | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index a4638387..3b3701dd 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -174,35 +174,13 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi } } - std::string schema; - auto host = strip_proto_name(node_ip, &schema); + node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); - try { - fc::ip::address ip_addr; - try { - // IP address assumed - ip_addr = fc::ip::address(host); - } catch (...) { - try { - // host name assumed - host = resolve_host_addr(host); - ip_addr = fc::ip::address(host); - } catch (...) { - elog("Failed to resolve Hive node address ${ip}", ("ip", node_ip)); - FC_ASSERT(false); - } - } - // try to connect to TCP endpoint - fc::http::connection conn; - conn.connect_to(fc::ip::endpoint(ip_addr, node_rpc_port)); - } catch (fc::exception &e) { + std::string chain_id_str = node_rpc_client->get_chain_id(); + if (chain_id_str.empty()) { elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); FC_ASSERT(false); } - - node_rpc_client = new hive_node_rpc_client(schema + host, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); - - std::string chain_id_str = node_rpc_client->get_chain_id(); chain_id = chain_id_type(chain_id_str); std::string is_test_net = node_rpc_client->get_is_test_net(); -- 2.45.2 From ac90d10841332ea0ff10428ca25a2b700ed77e90 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 2 Nov 2021 23:52:30 +0100 Subject: [PATCH 46/57] Add Hive delegate_vesting_shares_operation --- .../hive/hive_operations.hpp | 74 +++++++++++++++++-- .../peerplays_sidechain/hive/operations.hpp | 37 +++++++++- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp index e19060f8..1348ce35 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp @@ -13,7 +13,6 @@ namespace graphene { namespace peerplays_sidechain { namespace hive { struct vote_operation {}; - struct comment_operation {}; struct transfer_operation { @@ -24,17 +23,11 @@ struct transfer_operation { }; struct transfer_to_vesting_operation {}; - struct withdraw_vesting_operation {}; - struct limit_order_create_operation {}; - struct limit_order_cancel_operation {}; - struct feed_publish_operation {}; - struct convert_operation {}; - struct account_create_operation {}; struct account_update_operation { @@ -46,6 +39,42 @@ struct account_update_operation { std::string json_metadata; }; +struct witness_update_operation {}; +struct account_witness_vote_operation {}; +struct account_witness_proxy_operation {}; +struct pow_operation {}; +struct custom_operation {}; +struct report_over_production_operation {}; +struct delete_comment_operation {}; +struct custom_json_operation {}; +struct comment_options_operation {}; +struct set_withdraw_vesting_route_operation {}; +struct limit_order_create2_operation {}; +struct claim_account_operation {}; +struct create_claimed_account_operation {}; +struct request_account_recovery_operation {}; +struct recover_account_operation {}; +struct change_recovery_account_operation {}; +struct escrow_transfer_operation {}; +struct escrow_dispute_operation {}; +struct escrow_release_operation {}; +struct pow2_operation {}; +struct escrow_approve_operation {}; +struct transfer_to_savings_operation {}; +struct transfer_from_savings_operation {}; +struct cancel_transfer_from_savings_operation {}; +struct custom_binary_operation {}; +struct decline_voting_rights_operation {}; +struct reset_account_operation {}; +struct set_reset_account_operation {}; +struct claim_reward_balance_operation {}; + +struct delegate_vesting_shares_operation { + hive::account_name_type delegator; + hive::account_name_type delegatee; + hive::asset vesting_shares; +}; + }}} // namespace graphene::peerplays_sidechain::hive FC_REFLECT(graphene::peerplays_sidechain::hive::vote_operation, ) @@ -61,3 +90,34 @@ FC_REFLECT(graphene::peerplays_sidechain::hive::convert_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::account_create_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::account_update_operation, (account)(owner)(active)(posting)(memo_key)(json_metadata)) +FC_REFLECT(graphene::peerplays_sidechain::hive::witness_update_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_witness_vote_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_witness_proxy_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::pow_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::custom_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::report_over_production_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::delete_comment_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::custom_json_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::comment_options_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::set_withdraw_vesting_route_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create2_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::claim_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::create_claimed_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::request_account_recovery_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::recover_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::change_recovery_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_transfer_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_dispute_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_release_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::pow2_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_approve_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_savings_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_from_savings_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::cancel_transfer_from_savings_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::custom_binary_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::decline_voting_rights_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::reset_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::set_reset_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::claim_reward_balance_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::delegate_vesting_shares_operation, + (delegator)(delegatee)(vesting_shares)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp index 42550dc2..e64eb1ae 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp @@ -19,7 +19,42 @@ typedef fc::static_variant< convert_operation, account_create_operation, - account_update_operation> + account_update_operation, + + witness_update_operation, + account_witness_vote_operation, + account_witness_proxy_operation, + + pow_operation, + + custom_operation, + + report_over_production_operation, + + delete_comment_operation, + custom_json_operation, + comment_options_operation, + set_withdraw_vesting_route_operation, + limit_order_create2_operation, + claim_account_operation, + create_claimed_account_operation, + request_account_recovery_operation, + recover_account_operation, + change_recovery_account_operation, + escrow_transfer_operation, + escrow_dispute_operation, + escrow_release_operation, + pow2_operation, + escrow_approve_operation, + transfer_to_savings_operation, + transfer_from_savings_operation, + cancel_transfer_from_savings_operation, + custom_binary_operation, + decline_voting_rights_operation, + reset_account_operation, + set_reset_account_operation, + claim_reward_balance_operation, + delegate_vesting_shares_operation> hive_operation; }}} // namespace graphene::peerplays_sidechain::hive -- 2.45.2 From d95de9fea06655d9666fd9f12605a2143e5b186a Mon Sep 17 00:00:00 2001 From: serkixenos Date: Wed, 3 Nov 2021 03:39:30 +0100 Subject: [PATCH 47/57] Fix pBTC burning on withdrawal --- .../peerplays_sidechain/sidechain_net_handler_bitcoin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index bc50cee7..ca4e9149 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1546,7 +1546,7 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain if (sto.object_id.is()) { auto swwo = database.get(sto.object_id); - settle_amount = swwo.withdraw_amount; + settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.btc_asset()); return true; } } -- 2.45.2 From 1943f5deaf6555c411684076132f62bbd3f04e5d Mon Sep 17 00:00:00 2001 From: moss9001 Date: Fri, 5 Nov 2021 23:34:03 +0200 Subject: [PATCH 48/57] HTTPS and connect test fixed --- .../peerplays_sidechain/common/rpc_client.cpp | 559 +++++++++--------- .../peerplays_sidechain/common/rpc_client.hpp | 50 +- .../sidechain_net_handler_hive.cpp | 55 +- 3 files changed, 325 insertions(+), 339 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 1db7c889..91ac8c36 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -3,9 +3,10 @@ #include #include -#include +//#include +//#include + #include -#include #include #include @@ -21,303 +22,269 @@ namespace graphene { namespace peerplays_sidechain { -struct http_request { - - std::string method; // ex: "POST" - std::string path; // ex: "/" - std::string headers; - std::string body; - std::string content_type; // ex: "application/json" - - http_request() { - } - - http_request(const std::string &method_, const std::string &path_, const std::string &headers_, const std::string &body_, const std::string &content_type_) : - method(method_), - path(path_), - headers(headers_), - body(body_), - content_type(content_type_) { - } - - http_request(const std::string &method_, const std::string &path_, const std::string &headers_, const std::string &body_ = std::string()) : - method(method_), - path(path_), - headers(headers_), - body(body_), - content_type("application/json") { - } - - void clear() { - method.clear(); - path.clear(); - headers.clear(); - body.clear(); - content_type.clear(); - } -}; - -struct http_response { - - uint16_t status_code; - std::string body; - - void clear() { - status_code = 0; - body = decltype(body)(); - } -}; - -class https_call { -public: - https_call(const std::string &host, uint16_t port = 0) : - m_host(host), - m_port(port) { - } - - const std::string &host() const { - return m_host; - } - - uint16_t port() const { - return m_port; - } - - uint32_t response_size_limit_bytes() const { - return 1024 * 1024; - } - - bool exec(const http_request &request, http_response *response); - -private: - std::string m_host; - uint16_t m_port; -}; +using namespace boost::asio; namespace detail { +// https_call_impl + +class https_call_impl { +public: + https_call_impl(https_call &call, const void *body_data, size_t body_size, http_response &response); + void exec(); + +private: + https_call &m_call; + const void *m_body_data; + size_t m_body_size; + http_response &m_response; + + ssl::stream m_socket; + streambuf m_response_buf; + int32_t m_content_length; + +private: + void connect(); + void send_request(); + void process_headers(); + void process_response(); +}; + static const char cr = 0x0D; static const char lf = 0x0A; static const char *crlf = "\x0D\x0A"; static const char *crlfcrlf = "\x0D\x0A\x0D\x0A"; -using namespace boost::asio; +https_call_impl::https_call_impl(https_call &call, const void *body_data, size_t body_size, http_response &response) : + m_call(call), + m_body_data(body_data), + m_body_size(body_size), + m_response(response), + m_socket(m_call.m_service, m_call.m_context), + m_response_buf(https_call::response_size_limit_bytes) { +} -class https_call_impl { -public: - https_call_impl(const https_call &call, const http_request &request, http_response &response) : - m_call(call), - m_request(request), - m_response(response), - m_service(), - m_context(ssl::context::tlsv12_client), - m_socket(m_service, m_context), - m_endpoint(), - m_response_buf(call.response_size_limit_bytes()), - m_content_length(0) { - m_context.set_default_verify_paths(); +void https_call_impl::exec() { + connect(); + send_request(); + process_response(); +} + +void https_call_impl::connect() { + + // TCP connect + + m_socket.lowest_layer().connect(m_call.m_endpoint); + + // SSL connect + + if (!SSL_set_tlsext_host_name(m_socket.native_handle(), m_call.m_host.c_str())) { + FC_THROW("SSL_set_tlsext_host_name failed"); } - void exec() { - resolve(); - connect(); - send_request(); - process_response(); + m_socket.set_verify_mode(ssl::verify_peer); + m_socket.handshake(ssl::stream_base::client); +} + +void https_call_impl::send_request() { + + streambuf request; + std::ostream stream(&request); + + // start string: HTTP/1.0 + + stream << m_call.m_method << " " << m_call.m_path << " HTTP/1.0" << crlf; + + // host + + stream << "Host: " << m_call.m_host << ":" << m_call.m_endpoint.port() << crlf; + + // content + + if (m_body_size) { + stream << "Content-Type: " << m_call.m_content_type << crlf; + stream << "Content-Length: " << m_body_size << crlf; } -private: - const https_call &m_call; - const http_request &m_request; - http_response &m_response; + // additional headers - io_service m_service; - ssl::context m_context; - ssl::stream m_socket; - ip::tcp::endpoint m_endpoint; - streambuf m_response_buf; - uint32_t m_content_length; + const auto &h = m_call.m_headers; - void resolve() { - - // resolve TCP endpoint for host name - - ip::tcp::resolver resolver(m_service); - auto query = ip::tcp::resolver::query(m_call.host(), "https"); - auto iter = resolver.resolve(query); - m_endpoint = *iter; - - if (m_call.port() != 0) // if port was specified - m_endpoint.port(m_call.port()); // force set port - } - - void connect() { - - // TCP connect - - m_socket.lowest_layer().connect(m_endpoint); - - // SSL connect - - m_socket.set_verify_mode(ssl::verify_peer); - m_socket.handshake(ssl::stream_base::client); - } - - void send_request() { - - streambuf request_buf; - std::ostream stream(&request_buf); - - // start string: HTTP/1.0 - - stream << m_request.method << " " << m_request.path << " HTTP/1.0" << crlf; - - // host - - stream << "Host: " << m_call.host(); - - if (m_call.port() != 0) { - //ASSERT(m_Endpoint.port() == m_Call.port()); - stream << ":" << m_call.port(); + if (!h.empty()) { + if (h.size() < 2) { + FC_THROW("invalid headers data"); } - - stream << crlf; - - // content - - if (!m_request.body.empty()) { - stream << "Content-Type: " << m_request.content_type << crlf; - stream << "Content-Length: " << m_request.body.size() << crlf; - } - - // additional headers - - const auto &h = m_request.headers; - - if (!h.empty()) { - if (h.size() < 2) { - FC_THROW("invalid headers data"); - } - stream << h; - // ensure headers finished correctly - if ((h.substr(h.size() - 2) != crlf)) - stream << crlf; - } - - // other - - stream << "Accept: *\x2F*" << crlf; - stream << "Connection: close" << crlf; - - // end - - stream << crlf; - - // content - - if (!m_request.body.empty()) - stream << m_request.body; - - // send - - write(m_socket, request_buf); + stream << h; + // ensure headers finished correctly + if ((h.substr(h.size() - 2) != crlf)) + stream << crlf; } - void process_headers() { + // other - std::istream stream(&m_response_buf); + // stream << "Accept: *\x2F*" << crlf; + stream << "Accept: text/html, application/json" << crlf; + stream << "Connection: close" << crlf; - std::string http_version; - stream >> http_version; - stream >> m_response.status_code; + // end - if (!stream || http_version.substr(0, 5) != "HTTP/") { - FC_THROW("invalid response data"); - } + stream << crlf; - // read/skip headers + // send headers - for (;;) { - std::string header; - if (!std::getline(stream, header, lf) || (header.size() == 1 && header[0] == cr)) - break; - if (m_content_length) // if content length is already known - continue; // continue skipping headers - auto pos = header.find(':'); - if (pos == std::string::npos) - continue; - auto name = header.substr(0, pos); - boost::algorithm::trim(name); - boost::algorithm::to_lower(name); - if (name != "content-length") - continue; - auto value = header.substr(pos + 1); - boost::algorithm::trim(value); - m_content_length = std::stol(value); - } + write(m_socket, request); + + // send body + + if (m_body_size) + write(m_socket, buffer(m_body_data, m_body_size)); +} + +void https_call_impl::process_headers() { + + std::istream stream(&m_response_buf); + + std::string http_version; + stream >> http_version; + stream >> m_response.status_code; + + boost::algorithm::trim(http_version); + boost::algorithm::to_lower(http_version); + + if (!stream || http_version.substr(0, 5) != "http/") { + FC_THROW("invalid response data"); } - void process_response() { + // read/skip headers - auto &socket = m_socket; - auto &buf = m_response_buf; - auto &content_length = m_content_length; - auto &body = m_response.body; + m_content_length = -1; - read_until(socket, buf, crlfcrlf); + for (;;) { + std::string header; + if (!std::getline(stream, header, lf) || (header.size() == 1 && header[0] == cr)) + break; + if (m_content_length) // if content length is already known + continue; // continue skipping headers + auto pos = header.find(':'); + if (pos == std::string::npos) + continue; + auto name = header.substr(0, pos); + boost::algorithm::trim(name); + boost::algorithm::to_lower(name); + if (name != "content-length") + continue; + auto value = header.substr(pos + 1); + boost::algorithm::trim(value); + m_content_length = std::stol(value); + } +} - process_headers(); +void https_call_impl::process_response() { - // check content length + auto &socket = m_socket; + auto &buf = m_response_buf; + auto &content_length = m_content_length; + auto &body = m_response.body; + read_until(socket, buf, crlfcrlf); + + process_headers(); + + // check content length + + if (content_length >= 0) { if (content_length < 2) { // minimum content is "{}" FC_THROW("invalid response body (too short)"); } - - if (content_length > m_call.response_size_limit_bytes()) { + if (content_length > https_call::response_size_limit_bytes) { FC_THROW("response body size limit exceeded"); } + } - // read body + boost::system::error_code ec; - auto avail = buf.size(); // size of body data already stored in the buffer + for (;;) { - if (avail > content_length) { - FC_THROW("invalid response body (content length mismatch)"); + auto readed = read(socket, buf, transfer_at_least(1), ec); + + if (ec) + break; + + if (!readed) { + if (buf.size() == buf.max_size()) + FC_THROW("response body size limit exceeded"); + else + FC_THROW("logic error: read failed but no error conditon"); } - body.resize(content_length); - - if (avail) { - // copy already existing data - if (avail != buf.sgetn(&body[0], avail)) { - FC_THROW("stream read failed"); + if (content_length >= 0) { + if (buf.size() > content_length) { + FC_THROW("read more than content-length"); } } - - auto rest = content_length - avail; // size of remaining part of response body - - boost::system::error_code error_code; - - read(socket, buffer(&body[avail], rest), error_code); // read remaining part - - socket.shutdown(error_code); } -}; + + { + boost::system::error_code ec; + socket.shutdown(ec); + } + + if ((ec != error::eof) && + (ec != ssl::error::stream_truncated)) { + throw boost::system::system_error(ec); + } + + if (content_length >= 0) { + if (buf.size() != content_length) { + FC_THROW("actual body size differs from content-length"); + } + } + + auto size = buf.size(); + body.resize(size); + if (size != buf.sgetn(&body[0], size)) { + FC_THROW("stream read failed"); + } +} } // namespace detail -bool https_call::exec(const http_request &request, http_response *response) { +// https_call - // ASSERT(response); +https_call::https_call(const std::string &host, const std::string &ip_addr, uint16_t port, const std::string &method, const std::string &path, const std::string &headers, const std::string &content_type) : + m_host(host), + m_method(method), + m_path(path), + m_headers(headers), + m_content_type(content_type), + m_service(), + m_context(ssl::context::tlsv12_client), + m_endpoint(ip::address::from_string(ip_addr), port) { + m_context.set_default_verify_paths(); + m_context.set_options(ssl::context::default_workarounds); +} + +bool https_call::exec(const void *body_data, size_t body_size, http_response *response) { + + //ASSERT(response); auto &resp = *response; - detail::https_call_impl impl(*this, request, resp); + detail::https_call_impl impl(*this, body_data, body_size, resp); + + m_error_what = decltype(m_error_what)(); try { - resp.clear(); - impl.exec(); + try { + resp.clear(); + impl.exec(); + } catch (const std::exception &e) { + resp.clear(); + m_error_what = e.what(); + return false; + } } catch (...) { resp.clear(); + m_error_what = "unknown exception"; return false; } @@ -328,15 +295,64 @@ bool https_call::exec(const http_request &request, http_response *response) { namespace graphene { namespace peerplays_sidechain { -rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : - ip(_ip), +static std::string resolve_host_addr(const std::string &host_name) { + using namespace boost::asio; + io_service service; + ip::tcp::resolver resolver(service); + auto query = ip::tcp::resolver::query(host_name, std::string()); + auto iter = resolver.resolve(query); + auto endpoint = *iter; + auto addr = ((ip::tcp::endpoint)endpoint).address(); + return addr.to_string(); +} + +static std::string strip_proto_name(const std::string &url, std::string *schema) { + auto index = url.find("://"); + if (index == std::string::npos) { + if (schema) + schema->clear(); + return url; + } + if (schema) + schema->assign(&url[0], &url[index]); + return url.substr(index + 3); +} + +}} // namespace graphene::peerplays_sidechain + +namespace graphene { namespace peerplays_sidechain { + +rpc_client::rpc_client(std::string url, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : port(_port), user(_user), password(_password), debug_rpc_calls(_debug_rpc_calls), request_id(0) { + authorization.key = "Authorization"; authorization.val = "Basic " + fc::base64_encode(user + ":" + password); + + std::string schema; + host = strip_proto_name(url, &schema); + boost::algorithm::to_lower(schema); + + try { + fc::ip::address(host); // try to convert host string to valid IPv4 address + ip = host; + } catch (...) { + try { + ip = resolve_host_addr(host); + fc::ip::address(ip); + } catch (...) { + elog("Failed to resolve Hive node address ${ip}", ("ip", url)); + FC_ASSERT(false); + } + } + + if (schema == "https") + https = new https_call(host, ip, port, "POST", "/", authorization.key + ":" + authorization.val, "application/json"); + else + https = 0; } std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) { @@ -406,7 +422,7 @@ std::string rpc_client::send_post_request(std::string method, std::string params boost::property_tree::ptree json; boost::property_tree::read_json(ss, json); - if (reply.status == 200) { + if (reply.status_code == 200) { return ss.str(); } @@ -416,43 +432,18 @@ 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) { +http_response rpc_client::send_post_request(std::string body, bool show_log) { - rpc_reply reply; - auto start = ip.substr(0, 6); - boost::algorithm::to_lower(start); + http_response response; - if (start == "https:") { + if (https) { - auto host = ip.substr(8); // skip "https://" - - https_call call(host, port); - http_request request("POST", "/", authorization.key + ":" + authorization.val, body); - http_response response; - - if (call.exec(request, &response)) { - reply.status = response.status_code; - reply.body.resize(response.body.size()); - memcpy(&reply.body[0], &response.body[0], response.body.size()); - } + https->exec(body.c_str(), body.size(), &response); } else { - std::string host; - - if (start == "http:/") - host = ip.substr(7); // skip "http://" - else - host = ip; - std::string url = "http://" + host + ":" + std::to_string(port); - fc::ip::address addr; - - try { - addr = fc::ip::address(host); - } catch (...) { - return reply; - } + fc::ip::address addr(ip); try { @@ -464,22 +455,22 @@ rpc_reply rpc_client::send_post_request(std::string body, bool show_log) { //} auto r = conn.request("POST", url, body, fc::http::headers{authorization}); - reply.status = r.status; - reply.body.assign(r.body.begin(), r.body.end()); + response.status_code = r.status; + response.body.assign(r.body.begin(), r.body.end()); } catch (...) { } } if (show_log) { - std::string url = ip + ":" + std::to_string(port); + std::string url = host + ":" + std::to_string(port); ilog("### Request URL: ${url}", ("url", url)); ilog("### Request: ${body}", ("body", body)); - std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + std::stringstream ss(std::string(response.body.begin(), response.body.end())); ilog("### Response: ${ss}", ("ss", ss.str())); } - return reply; + return response; } }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index f61bdb3f..d8706b9d 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -5,22 +5,63 @@ #include +#include +#include + namespace graphene { namespace peerplays_sidechain { -struct rpc_reply { - uint16_t status; +struct http_response { + + uint16_t status_code; std::string body; + + void clear() { + status_code = 0; + body = decltype(body)(); + } }; +namespace detail { +class https_call_impl; +} // namespace detail + +class https_call { +public: + https_call(const std::string &host, const std::string &ip_addr, uint16_t port, const std::string &method, const std::string &path, const std::string &headers, const std::string &content_type); + + bool exec(const void *body_data, size_t body_size, http_response *response); + + const std::string &error_what() const; + +private: + friend class detail::https_call_impl; + static constexpr auto response_size_limit_bytes = 1024 * 1024; + std::string m_host; + std::string m_method; + std::string m_path; + std::string m_headers; + std::string m_content_type; + std::string m_error_what; + + boost::asio::io_service m_service; + boost::asio::ssl::context m_context; + boost::asio::ip::tcp::endpoint m_endpoint; +}; + +}} // namespace graphene::peerplays_sidechain + +namespace graphene { namespace peerplays_sidechain { + class rpc_client { public: - rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls); + rpc_client(std::string url, uint32_t _port, 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 host; std::string ip; uint32_t port; std::string user; @@ -32,8 +73,9 @@ protected: fc::http::header authorization; private: + https_call *https; //fc::http::reply send_post_request(std::string body, bool show_log); - rpc_reply send_post_request(std::string body, bool show_log); + http_response send_post_request(std::string body, bool show_log); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index a4638387..36ca5b2f 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -32,33 +32,6 @@ namespace graphene { namespace peerplays_sidechain { -std::string resolve_host_addr(const std::string &host_name) { - using namespace boost::asio; - io_service service; - ip::tcp::resolver resolver(service); - auto query = ip::tcp::resolver::query(host_name, std::string()); - auto iter = resolver.resolve(query); - auto endpoint = *iter; - auto addr = ((ip::tcp::endpoint)endpoint).address(); - return addr.to_string(); -} - -std::string strip_proto_name(const std::string &url, std::string *schema) { - auto index = url.find("://"); - if (index == std::string::npos) { - if (schema) - schema->clear(); - return url; - } - if (schema) - schema->assign(&url[0], &url[index + 3]); - return url.substr(index + 3); -} - -}} // namespace graphene::peerplays_sidechain - -namespace graphene { namespace peerplays_sidechain { - hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : rpc_client(_ip, _port, _user, _password, _debug_rpc_calls) { } @@ -174,35 +147,15 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi } } - std::string schema; - auto host = strip_proto_name(node_ip, &schema); + node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); - try { - fc::ip::address ip_addr; - try { - // IP address assumed - ip_addr = fc::ip::address(host); - } catch (...) { - try { - // host name assumed - host = resolve_host_addr(host); - ip_addr = fc::ip::address(host); - } catch (...) { - elog("Failed to resolve Hive node address ${ip}", ("ip", node_ip)); - FC_ASSERT(false); - } - } - // try to connect to TCP endpoint - fc::http::connection conn; - conn.connect_to(fc::ip::endpoint(ip_addr, node_rpc_port)); - } catch (fc::exception &e) { + std::string chain_id_str = node_rpc_client->get_chain_id(); + + if (chain_id_str.empty()) { elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); FC_ASSERT(false); } - node_rpc_client = new hive_node_rpc_client(schema + host, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); - - std::string chain_id_str = node_rpc_client->get_chain_id(); chain_id = chain_id_type(chain_id_str); std::string is_test_net = node_rpc_client->get_is_test_net(); -- 2.45.2 From 7f0900de57798e985c00704bdba8cbc6ae470f4f Mon Sep 17 00:00:00 2001 From: moss9001 Date: Sat, 6 Nov 2021 00:56:44 +0200 Subject: [PATCH 49/57] Update rpc_client.cpp --- libraries/plugins/peerplays_sidechain/common/rpc_client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 91ac8c36..0cc7c63d 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -337,12 +337,12 @@ rpc_client::rpc_client(std::string url, uint32_t _port, std::string _user, std:: boost::algorithm::to_lower(schema); try { - fc::ip::address(host); // try to convert host string to valid IPv4 address + fc::ip::address temp(host); // try to convert host string to valid IPv4 address ip = host; } catch (...) { try { ip = resolve_host_addr(host); - fc::ip::address(ip); + fc::ip::address temp(ip); } catch (...) { elog("Failed to resolve Hive node address ${ip}", ("ip", url)); FC_ASSERT(false); -- 2.45.2 From b75a8fe6a8a10d62e8ead8007804b40d7eb92daa Mon Sep 17 00:00:00 2001 From: moss9001 Date: Tue, 16 Nov 2021 14:27:35 +0200 Subject: [PATCH 50/57] New implementation of HTTP protocol class --- .../peerplays_sidechain/common/rpc_client.cpp | 900 +++++++++++++----- .../peerplays_sidechain/common/rpc_client.hpp | 100 +- .../sidechain_net_handler_hive.cpp | 16 +- 3 files changed, 775 insertions(+), 241 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 91667f4d..9af14dcf 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -3,7 +3,7 @@ #include #include -#include +//#include #include #include @@ -17,29 +17,328 @@ namespace graphene { namespace peerplays_sidechain { +constexpr auto http_port = 80; +constexpr auto https_port = 443; + +template +void make_trimmed(string *str) { + boost::algorithm::trim(*str); +} + +template +void make_lower(string *str) { + boost::algorithm::to_lower(*str); +} + +bool convert_hex_to_num_helper1(const std::string &str, uint32_t *value) { + try { + size_t idx; + auto v = stol(str, &idx, 16); + if (idx != str.size()) + return false; + if (value) + *value = v; + return true; + } catch (...) { + return false; + } +} + +bool convert_dec_to_num_helper1(const std::string &str, uint32_t *value) { + try { + size_t idx; + auto v = stol(str, &idx, 10); + if (idx != str.size()) + return false; + if (value) + *value = v; + return true; + } catch (...) { + return false; + } +} + +bool convert_dec_to_num_helper1(const std::string &str, uint16_t *value) { + try { + size_t idx; + auto v = stol(str, &idx, 10); + if (idx != str.size()) + return false; + if (v > std::numeric_limits::max()) + return false; + if (value) + *value = v; + return true; + } catch (...) { + return false; + } +} + +template +constexpr V ceilDiv(V value, D divider) { + return (value + divider - 1) / divider; +} + +template +constexpr V aligned(V value, A align) { + return ceilDiv(value, align) * align; +} + +template +void reserve( + Container *container, + typename Container::size_type freeSpaceRequired, + typename Container::size_type firstAlloc, + typename Container::size_type nextAlloc) { + //TSL_ASSERT(container); + auto &c = *container; + auto required = c.size() + freeSpaceRequired; + if (c.capacity() >= required) + return; + c.reserve((firstAlloc >= required) ? firstAlloc + : firstAlloc + aligned(required - firstAlloc, nextAlloc)); +} + +template +void reserve( + Container *container, + typename Container::size_type freeSpaceRequired, + typename Container::size_type alloc) { + //TSL_ASSERT(container); + auto &c = *container; + auto required = c.size() + freeSpaceRequired; + if (c.capacity() >= required) + return; + c.reserve(aligned(required, alloc)); +} + +bool is_valid(const boost::asio::ip::tcp::endpoint &ep) { + + if (ep.port() == 0) + return false; + + if (ep.address().is_unspecified()) + return false; + + return true; +} + +// utl + +url_schema_type identify_url_schema_type(const std::string &schema_name) { + // rework + auto temp = schema_name; + make_lower(&temp); + if (temp == "http") + return url_schema_type::http; + if (temp == "https") + return url_schema_type::https; + return url_schema_type::unknown; +} + +// url_data + +url_data::url_data(const std::string &url) { + if (!parse(url)) + FC_THROW("URL parse failed"); +} + +void url_data::clear() { + schema_type = url_schema_type::unknown; + schema = decltype(schema)(); + host = decltype(host)(); + port = 0; + path = decltype(path)(); +} + +bool url_data::parse(const std::string &url) { + + typedef std::string::size_type size_t; + constexpr auto npos = std::string::npos; + + size_t schema_end = url.find("://"); + size_t host_begin; + std::string temp_schema; + + if (schema_end == npos) + host_begin = 0; // no schema + else { + if (schema_end < 3) { // schema too short: less than 3 chars + return false; + } + if (schema_end > 5) { // schema too long: more than 5 chars + return false; + } + host_begin = schema_end + 3; + temp_schema = url.substr(0, schema_end); + } + + // ASSERT(url.size() >= host_begin); + + if (url.size() == host_begin) // host is empty + return false; + + size_t port_sep = url.find(':', host_begin); + + if (port_sep == host_begin) + return false; + + size_t path_sep = url.find('/', host_begin); + + if (path_sep == host_begin) + return false; + + if ((port_sep != npos) && (path_sep != npos) && (port_sep > path_sep)) + port_sep = npos; + + std::string temp_port; + + if (port_sep != npos) { + auto port_index = port_sep + 1; + if (path_sep == npos) + temp_port = url.substr(port_index); + else + temp_port = url.substr(port_index, path_sep - port_index); + } + + if (temp_port.empty()) + port = 0; + else { + if (!convert_dec_to_num_helper1(temp_port, &port)) + return false; + } + + std::string temp_path; + + if (path_sep != npos) + temp_path = url.substr(path_sep); + + std::string temp_host; + + if (port_sep != npos) { + temp_host = url.substr(host_begin, port_sep - host_begin); + } else { + if (path_sep != npos) + temp_host = url.substr(host_begin, path_sep - host_begin); + else + temp_host = url.substr(host_begin); + } + + schema = temp_schema; + host = temp_host; + path = temp_path; + schema_type = identify_url_schema_type(schema); + + return true; +} + +}} // namespace graphene::peerplays_sidechain + +namespace graphene { namespace peerplays_sidechain { + using namespace boost::asio; +using error_code = boost::system::error_code; +using endpoint = ip::tcp::endpoint; namespace detail { -class https_call_impl { +// http_call_impl + +struct tcp_socket { + + typedef ip::tcp::socket underlying_type; + + underlying_type underlying; + + tcp_socket(http_call &call) : + underlying(call.m_service) { + } + + underlying_type &operator()() { + return underlying; + } + + void connect(const http_call &call, const endpoint &ep, error_code *ec) { + // TCP connect + underlying.connect(ep, *ec); + } + + void shutdown() { + error_code ec; + underlying.close(ec); + } +}; + +struct ssl_socket { + + typedef ssl::stream underlying_type; + + underlying_type underlying; + + ssl_socket(http_call &call) : + underlying(call.m_service, *call.m_context) { + } + + underlying_type &operator()() { + return underlying; + } + + void connect(const http_call &call, const endpoint &ep, error_code *ec) { + + auto &u = underlying; + + // TCP connect + u.lowest_layer().connect(ep, *ec); + + // SSL connect + if (!SSL_set_tlsext_host_name(u.native_handle(), call.m_host.c_str())) + FC_THROW("SSL_set_tlsext_host_name failed"); + + u.set_verify_mode(ssl::verify_peer, *ec); + u.handshake(ssl::stream_base::client, *ec); + } + + void shutdown() { + auto &u = underlying; + error_code ec; + u.shutdown(ec); + u.lowest_layer().close(ec); + } +}; + +template +class http_call_impl { public: - https_call_impl(https_call &call, const void *body_data, size_t body_size, http_response &response); + http_call_impl(http_call &call, const void *body_data, size_t body_size, const std::string &content_type_, http_response &response); void exec(); private: - https_call &m_call; - const void *m_body_data; - size_t m_body_size; - http_response &m_response; + http_call &call; + const void *body_data; + size_t body_size; + std::string content_type; + http_response &response; - ssl::stream m_socket; - streambuf m_response_buf; - int32_t m_content_length; + socket_type socket; + streambuf response_buf; + + int32_t content_length; + bool transfer_encoding_chunked; private: void connect(); + void shutdown(); void send_request(); + void on_header(std::string &name, std::string &value); + void on_header(); void process_headers(); + void append_entity_body(std::istream *stream, size_t size); + void append_entity_body_2(std::istream *strm); + bool read_next_chunk(std::istream *strm); + void skip_footer(); + void read_body_chunked(); + void read_body_until_eof(); + void read_body_exact(); void process_response(); }; @@ -47,66 +346,102 @@ static const char cr = 0x0D; static const char lf = 0x0A; static const char *crlf = "\x0D\x0A"; static const char *crlfcrlf = "\x0D\x0A\x0D\x0A"; +static const auto crlf_uint = (((uint16_t)lf) << 8) + cr; -https_call_impl::https_call_impl(https_call &call, const void *body_data, size_t body_size, http_response &response) : - m_call(call), - m_body_data(body_data), - m_body_size(body_size), - m_response(response), - m_socket(m_call.m_service, m_call.m_context), - m_response_buf(https_call::response_size_limit_bytes) { +template +http_call_impl::http_call_impl(http_call &call_, const void *body_data_, size_t body_size_, const std::string &content_type_, http_response &response_) : + call(call_), + body_data(body_data_), + body_size(body_size_), + content_type(content_type_), + response(response_), + socket(call), + response_buf(http_call::response_size_limit_bytes) { } -void https_call_impl::exec() { - connect(); - send_request(); - process_response(); +template +void http_call_impl::exec() { + try { + connect(); + send_request(); + process_response(); + shutdown(); + } catch (...) { + shutdown(); + throw; + } } -void https_call_impl::connect() { +template +void http_call_impl::connect() { - // TCP connect - - m_socket.lowest_layer().connect(m_call.m_endpoint); - - // SSL connect - - if (!SSL_set_tlsext_host_name(m_socket.native_handle(), m_call.m_host.c_str())) { - FC_THROW("SSL_set_tlsext_host_name failed"); + { + error_code ec; + auto &ep = call.m_endpoint; + if (is_valid(ep)) { + socket.connect(call, ep, &ec); + if (!ec) + return; + } } - m_socket.set_verify_mode(ssl::verify_peer); - m_socket.handshake(ssl::stream_base::client); + ip::tcp::resolver resolver(call.m_service); + + auto rng = resolver.resolve(call.m_host, std::string()); + + //ASSERT(rng.begin() != rng.end()); + + error_code ec; + + for (endpoint ep : rng) { + ep.port(call.m_port); + socket.connect(call, ep, &ec); + if (!ec) { + call.m_endpoint = ep; + return; // comment to test1 + } + } + // if (!ec) return; // uncomment to test1 + + //ASSERT(ec); + throw boost::system::system_error(ec); } -void https_call_impl::send_request() { +template +void http_call_impl::shutdown() { + socket.shutdown(); +} + +template +void http_call_impl::send_request() { streambuf request; std::ostream stream(&request); // start string: HTTP/1.0 - stream << m_call.m_method << " " << m_call.m_path << " HTTP/1.0" << crlf; + //ASSERT(!call.m_path.empty()); + + stream << call.m_method << " " << call.m_path << " HTTP/1.1" << crlf; // host - stream << "Host: " << m_call.m_host << ":" << m_call.m_endpoint.port() << crlf; + stream << "Host: " << call.m_host << ":" << call.m_endpoint.port() << crlf; // content - if (m_body_size) { - stream << "Content-Type: " << m_call.m_content_type << crlf; - stream << "Content-Length: " << m_body_size << crlf; + if (body_size) { + stream << "Content-Type: " << content_type << crlf; + stream << "Content-Length: " << body_size << crlf; } // additional headers - const auto &h = m_call.m_headers; + const auto &h = call.m_headers; if (!h.empty()) { - if (h.size() < 2) { + if (h.size() < 2) FC_THROW("invalid headers data"); - } stream << h; // ensure headers finished correctly if ((h.substr(h.size() - 2) != crlf)) @@ -125,61 +460,217 @@ void https_call_impl::send_request() { // send headers - write(m_socket, request); + write(socket(), request); // send body - if (m_body_size) - write(m_socket, buffer(m_body_data, m_body_size)); + if (body_size) + write(socket(), buffer(body_data, body_size)); } -void https_call_impl::process_headers() { +template +void http_call_impl::on_header(std::string &name, std::string &value) { - std::istream stream(&m_response_buf); + if (name == "content-length") { + uint32_t u; + if (!convert_dec_to_num_helper1(value, &u)) + FC_THROW("invalid content-length header data"); + content_length = u; + return; + } + + if (name == "transfer-encoding") { + boost::algorithm::to_lower(value); + if (value == "chunked") + transfer_encoding_chunked = true; + return; + } +} + +template +void http_call_impl::process_headers() { + + std::istream stream(&response_buf); std::string http_version; stream >> http_version; - stream >> m_response.status_code; + stream >> response.status_code; - boost::algorithm::trim(http_version); - boost::algorithm::to_lower(http_version); + make_trimmed(&http_version); + make_lower(&http_version); - if (!stream || http_version.substr(0, 5) != "http/") { + if (!stream || http_version.substr(0, 6) != "http/1") FC_THROW("invalid response data"); - } // read/skip headers - m_content_length = -1; + content_length = -1; + transfer_encoding_chunked = false; for (;;) { std::string header; if (!std::getline(stream, header, lf) || (header.size() == 1 && header[0] == cr)) break; - if (m_content_length) // if content length is already known - continue; // continue skipping headers auto pos = header.find(':'); if (pos == std::string::npos) continue; auto name = header.substr(0, pos); - boost::algorithm::trim(name); + make_trimmed(&name); boost::algorithm::to_lower(name); - if (name != "content-length") - continue; auto value = header.substr(pos + 1); - boost::algorithm::trim(value); - m_content_length = std::stol(value); + make_trimmed(&value); + on_header(name, value); } } -void https_call_impl::process_response() { +template +void http_call_impl::append_entity_body(std::istream *strm, size_t size) { + if (size == 0) + return; + auto &body = response.body; + reserve(&body, size, http_call::response_first_alloc_bytes, http_call::response_next_alloc_bytes); + auto cur = body.size(); + body.resize(cur + size); + auto p = &body[cur]; + if (!strm->read(p, size)) + FC_THROW("stream read failed"); +} - auto &socket = m_socket; - auto &buf = m_response_buf; - auto &content_length = m_content_length; - auto &body = m_response.body; +template +void http_call_impl::append_entity_body_2(std::istream *strm) { + auto avail = response_buf.size(); + if (response.body.size() + avail > http_call::response_size_limit_bytes) + FC_THROW("response body size limit exceeded"); + append_entity_body(strm, avail); +} - read_until(socket, buf, crlfcrlf); +template +bool http_call_impl::read_next_chunk(std::istream *strm) { + + // content length info is used as pre-alloc hint only + // it is not used inside the reading logic + + auto &buf = response_buf; + auto &stream = *strm; + auto &body = response.body; + + read_until(socket(), buf, crlf); + + std::string chunk_header; + + if (!std::getline(stream, chunk_header, lf)) + FC_THROW("failed to read chunk size"); + + auto ext_index = chunk_header.find(':'); + + if (ext_index != std::string::npos) + chunk_header.resize(ext_index); + + make_trimmed(&chunk_header); + + uint32_t chink_size; + + if (!convert_hex_to_num_helper1(chunk_header, &chink_size)) + FC_THROW("invalid chunk size string"); + + if (body.size() + chink_size > http_call::response_size_limit_bytes) + FC_THROW("response body size limit exceeded"); + + auto avail = buf.size(); + if (avail < chink_size + 2) { + auto rest = chink_size + 2 - avail; + read(socket(), buf, transfer_at_least(rest)); + } + + append_entity_body(&stream, chink_size); + + uint16_t temp; + if (!stream.read((char *)(&temp), 2)) + FC_THROW("stream read failed"); + if (temp != crlf_uint) + FC_THROW("invalid chink end"); + + return chink_size != 0; +} + +template +void http_call_impl::skip_footer() { + // to be implemeted +} + +template +void http_call_impl::read_body_chunked() { + + std::istream stream(&response_buf); + + for (;;) { + if (!read_next_chunk(&stream)) + break; + } + + skip_footer(); +} + +template +void http_call_impl::read_body_until_eof() { + + auto &buf = response_buf; + std::istream stream(&buf); + + append_entity_body_2(&stream); + + error_code ec; + + for (;;) { + auto readed = read(socket(), buf, transfer_at_least(1), ec); + append_entity_body_2(&stream); + if (ec) + break; + if (!readed) { + //ASSERT(buf.size() == 0); + FC_THROW("logic error: read failed but no error conditon"); + } + } + if ((ec != error::eof) && + (ec != ssl::error::stream_truncated)) + throw boost::system::system_error(ec); +} + +template +void http_call_impl::read_body_exact() { + + auto &buf = response_buf; + auto &body = response.body; + + auto avail = buf.size(); + + if (avail > content_length) + FC_THROW("invalid response body (content length mismatch)"); + + body.resize(content_length); + + if (avail) { + if (avail != buf.sgetn(&body[0], avail)) + FC_THROW("stream read failed"); + } + + auto rest = content_length - avail; + + if (rest > 0) { + auto readed = read(socket(), buffer(&body[avail], rest), transfer_exactly(rest)); + //ASSERT(readed <= rest); + if (readed < rest) + FC_THROW("logic error: read failed but no error conditon"); + } +} + +template +void http_call_impl::process_response() { + + auto &buf = response_buf; + auto &body = response.body; + + read_until(socket(), buf, crlfcrlf); process_headers(); @@ -189,151 +680,148 @@ void https_call_impl::process_response() { if (content_length < 2) { // minimum content is "{}" FC_THROW("invalid response body (too short)"); } - if (content_length > https_call::response_size_limit_bytes) { + if (content_length > http_call::response_size_limit_bytes) FC_THROW("response body size limit exceeded"); + body.reserve(content_length); + } + + if (transfer_encoding_chunked) { + read_body_chunked(); + } else { + if (content_length < 0) + read_body_until_eof(); + else { + if (content_length > 0) + read_body_exact(); } } - - boost::system::error_code ec; - - for (;;) { - - auto readed = read(socket, buf, transfer_at_least(1), ec); - - if (ec) - break; - - if (!readed) { - if (buf.size() == buf.max_size()) - FC_THROW("response body size limit exceeded"); - else - FC_THROW("logic error: read failed but no error conditon"); - } - - if (content_length >= 0) { - if (buf.size() > content_length) { - FC_THROW("read more than content-length"); - } - } - } - - { - boost::system::error_code ec; - socket.shutdown(ec); - } - - if ((ec != error::eof) && - (ec != ssl::error::stream_truncated)) { - throw boost::system::system_error(ec); - } - - if (content_length >= 0) { - if (buf.size() != content_length) { - FC_THROW("actual body size differs from content-length"); - } - } - - auto size = buf.size(); - body.resize(size); - if (size != buf.sgetn(&body[0], size)) { - FC_THROW("stream read failed"); - } } } // namespace detail -https_call::https_call(const std::string &host, const std::string &ip_addr, uint16_t port, const std::string &method, const std::string &path, const std::string &headers, const std::string &content_type) : - m_host(host), +// https_call + +http_call::http_call(const url_data &url, const std::string &method, const std::string &headers) : + m_host(url.host), m_method(method), - m_path(path), - m_headers(headers), - m_content_type(content_type), - m_service(), - m_context(ssl::context::tlsv12_client), - m_endpoint(ip::address::from_string(ip_addr), port) { - m_context.set_default_verify_paths(); - m_context.set_options(ssl::context::default_workarounds); + m_headers(headers) { + + if (url.schema_type == url_schema_type::https) { + m_context = new boost::asio::ssl::context(ssl::context::tlsv12_client); + } else { + m_context = 0; + } + + set_port(url.port); + set_path(url.path); + + try { + ctor_priv(); + } catch (...) { + if (m_context) + delete m_context; + throw; + } } -bool https_call::exec(const void *body_data, size_t body_size, http_response *response) { +http_call::~http_call() { + if (m_context) + delete m_context; +} + +bool http_call::is_ssl() const { + return m_context != 0; +} + +const std::string &http_call::path() const { + return m_path; +} + +void http_call::set_path(const std::string &path) { + if (path.empty()) + m_path = "/"; + else + m_path = path; +} + +void http_call::set_method(const std::string &method) { + m_method = method; +} + +void http_call::set_headers(const std::string &headers) { + m_headers = headers; +} + +const std::string &http_call::host() const { + return m_host; +} + +void http_call::set_host(const std::string &host) { + m_host = host; +} + +uint16_t http_call::port() const { + return m_port; +} + +void http_call::set_port(uint16_t port) { + if (port == 0) + m_port = is_ssl() ? https_port : http_port; + else + m_port = port; +} + +bool http_call::exec(const http_request &request, http_response *response) { //ASSERT(response); auto &resp = *response; - - detail::https_call_impl impl(*this, body_data, body_size, resp); - m_error_what = decltype(m_error_what)(); + resp.clear(); try { - resp.clear(); - impl.exec(); - } catch (const std::exception &e) { - resp.clear(); - m_error_what = e.what(); - return false; - } catch (...) { - resp.clear(); - m_error_what = "unknown exception"; - return false; - } - - return true; -} - -static std::string resolve_host_addr(const std::string &host_name) { - using namespace boost::asio; - io_service service; - ip::tcp::resolver resolver(service); - auto query = ip::tcp::resolver::query(host_name, std::string()); - auto iter = resolver.resolve(query); - auto endpoint = *iter; - auto addr = ((ip::tcp::endpoint)endpoint).address(); - return addr.to_string(); -} - -static std::string strip_proto_name(const std::string &url, std::string *schema) { - auto index = url.find("://"); - if (index == std::string::npos) { - if (schema) - schema->clear(); - return url; - } - if (schema) - schema->assign(&url[0], &url[index]); - return url.substr(index + 3); -} - -rpc_client::rpc_client(std::string url, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : - port(_port), - user(_user), - password(_password), - debug_rpc_calls(_debug_rpc_calls), - request_id(0) { - - authorization.key = "Authorization"; - authorization.val = "Basic " + fc::base64_encode(user + ":" + password); - - std::string schema; - host = strip_proto_name(url, &schema); - boost::algorithm::to_lower(schema); - - try { - fc::ip::address temp(host); // try to convert host string to valid IPv4 address - ip = host; - } catch (...) { try { - ip = resolve_host_addr(host); - fc::ip::address temp(ip); - } catch (...) { - elog("Failed to resolve Hive node address ${ip}", ("ip", url)); - FC_ASSERT(false); + using namespace detail; + if (!m_context) + http_call_impl(*this, request.body.data(), request.body.size(), request.content_type, resp).exec(); + else + http_call_impl(*this, request.body.data(), request.body.size(), request.content_type, resp).exec(); + return true; + } catch (const std::exception &e) { + m_error_what = e.what(); } + } catch (...) { + m_error_what = "unknown exception"; } - if (schema == "https") - https = new https_call(host, ip, port, "POST", "/", authorization.key + ":" + authorization.val, "application/json"); - else - https = 0; + resp.clear(); + return false; +} + +const std::string &http_call::error_what() const { + return m_error_what; +} + +void http_call::ctor_priv() { + if (m_context) { + m_context->set_default_verify_paths(); + m_context->set_options(ssl::context::default_workarounds); + } +} + +}} // namespace graphene::peerplays_sidechain + +namespace graphene { namespace peerplays_sidechain { + +rpc_client::rpc_client(const std::string &url, uint16_t port, const std::string &user_name, const std::string &password, bool debug) : + debug_rpc_calls(debug), + request_id(0), + client(url) + +{ + + client.set_method("POST"); + client.set_headers("Authorization : Basic" + fc::base64_encode(user_name + ":" + password)); + client.set_port(port); } std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) { @@ -494,38 +982,16 @@ std::string rpc_client::send_post_request(std::string method, std::string params // return reply; //} -http_response rpc_client::send_post_request(std::string body, bool show_log) { +http_response rpc_client::send_post_request(const std::string &body, bool show_log) { + http_request request(body, "application/json"); http_response response; - if (https) { - - https->exec(body.c_str(), body.size(), &response); - - } else { - - std::string url = "http://" + host + ":" + std::to_string(port); - fc::ip::address addr(ip); - - try { - - fc::http::connection conn; - conn.connect_to(fc::ip::endpoint(addr, port)); - - //if (wallet.length() > 0) { - // url = url + "/wallet/" + wallet; - //} - - auto r = conn.request("POST", url, body, fc::http::headers{authorization}); - response.status_code = r.status; - response.body.assign(r.body.begin(), r.body.end()); - - } catch (...) { - } - } + client.exec(request, &response); if (show_log) { - std::string url = host + ":" + std::to_string(port); + std::string url = client.is_ssl() ? "https" : "http"; + url = url + "://" + client.host() + std::to_string(client.port()) + client.path(); ilog("### Request URL: ${url}", ("url", url)); ilog("### Request: ${body}", ("body", body)); std::stringstream ss(std::string(response.body.begin(), response.body.end())); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index 0247b9bf..a83f9531 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -10,6 +10,45 @@ 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 { + + 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; @@ -22,57 +61,74 @@ struct http_response { }; namespace detail { -class https_call_impl; +template +class http_call_impl; +class tcp_socket; +class ssl_socket; } // namespace detail -class https_call { +class http_call { public: - https_call(const std::string &host, const std::string &ip_addr, uint16_t port, const std::string &method, const std::string &path, const std::string &headers, const std::string &content_type); + http_call(const url_data &url, const std::string &method = std::string(), const std::string &headers = std::string()); + ~http_call(); - bool exec(const void *body_data, size_t body_size, http_response *response); + 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: - friend class detail::https_call_impl; - static constexpr auto response_size_limit_bytes = 1024 * 1024; + template + friend class detail::http_call_impl; + friend detail::tcp_socket; + friend detail::ssl_socket; + static constexpr auto response_size_limit_bytes = 1024 * 1024 * 1024; + static constexpr auto response_first_alloc_bytes = 32 * 1024; + static constexpr auto response_next_alloc_bytes = 256 * 1024; std::string m_host; - std::string m_method; + uint16_t m_port; std::string m_path; + std::string m_method; std::string m_headers; - std::string m_content_type; std::string m_error_what; boost::asio::io_service m_service; - boost::asio::ssl::context m_context; + 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(std::string url, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls); + rpc_client(const std::string &url, uint16_t port, const std::string &user_name, const std::string &password, bool debug); 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 host; - std::string ip; - uint32_t port; - std::string user; - std::string password; bool debug_rpc_calls; - uint32_t request_id; - fc::http::header authorization; - private: - https_call *https; - //fc::http::reply send_post_request(std::string body, bool show_log); - //rpc_reply send_post_request(std::string body, bool show_log); - http_response send_post_request(std::string body, bool show_log); + http_call client; + http_response send_post_request(const std::string &body, bool show_log); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index ca5ea660..8791ed92 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -122,8 +122,20 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi debug_rpc_calls = options.at("debug-rpc-calls").as(); } - node_ip = options.at("hive-node-ip").as(); - node_rpc_port = options.at("hive-node-rpc-port").as(); + if ((options.count("hive-node-url") > 0) && (options.count("hive-node-ip") > 0)) + FC_THROW("both keys are present: hive-node-url and hive-node-ip"); + + if (options.count("hive-node-ip")) + node_ip = options.at("hive-node-ip").as(); + + if (options.count("hive-node-url")) + node_ip = options.at("hive-node-url").as(); + + + if (options.count("hive-node-rpc-port")) + node_rpc_port = options.at("hive-node-rpc-port").as(); + else + node_rpc_port = 0; if (options.count("hive-node-rpc-user")) { node_rpc_user = options.at("hive-node-rpc-user").as(); } else { -- 2.45.2 From f638caa8faea73f932315bf75aed94fdb52f43ad Mon Sep 17 00:00:00 2001 From: moss9001 Date: Tue, 16 Nov 2021 14:28:50 +0200 Subject: [PATCH 51/57] Update sidechain_net_handler_hive.cpp Clang formatted --- .../sidechain_net_handler_hive.cpp | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 8791ed92..fdde2376 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -122,20 +122,19 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi debug_rpc_calls = options.at("debug-rpc-calls").as(); } - if ((options.count("hive-node-url") > 0) && (options.count("hive-node-ip") > 0)) - FC_THROW("both keys are present: hive-node-url and hive-node-ip"); + if ((options.count("hive-node-url") > 0) && (options.count("hive-node-ip") > 0)) + FC_THROW("both keys are present: hive-node-url and hive-node-ip"); - if (options.count("hive-node-ip")) - node_ip = options.at("hive-node-ip").as(); + if (options.count("hive-node-ip")) + node_ip = options.at("hive-node-ip").as(); - if (options.count("hive-node-url")) - node_ip = options.at("hive-node-url").as(); + if (options.count("hive-node-url")) + node_ip = options.at("hive-node-url").as(); - - if (options.count("hive-node-rpc-port")) - node_rpc_port = options.at("hive-node-rpc-port").as(); - else - node_rpc_port = 0; + if (options.count("hive-node-rpc-port")) + node_rpc_port = options.at("hive-node-rpc-port").as(); + else + node_rpc_port = 0; if (options.count("hive-node-rpc-user")) { node_rpc_user = options.at("hive-node-rpc-user").as(); } else { -- 2.45.2 From 79c660e1c84089cc037c97a7fdf7033073cf66eb Mon Sep 17 00:00:00 2001 From: moss9001 Date: Sun, 21 Nov 2021 14:08:48 +0200 Subject: [PATCH 52/57] Minor fixes Semicolon placed between host and port at debug string --- libraries/plugins/peerplays_sidechain/common/rpc_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index 9af14dcf..a2a84997 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -991,7 +991,7 @@ http_response rpc_client::send_post_request(const std::string &body, bool show_l if (show_log) { std::string url = client.is_ssl() ? "https" : "http"; - url = url + "://" + client.host() + std::to_string(client.port()) + client.path(); + url = url + "://" + client.host() + ":" + std::to_string(client.port()) + client.path(); ilog("### Request URL: ${url}", ("url", url)); ilog("### Request: ${body}", ("body", body)); std::stringstream ss(std::string(response.body.begin(), response.body.end())); -- 2.45.2 From b09e74e237a57d78d37c8d4bb43432e6fd086d2d Mon Sep 17 00:00:00 2001 From: moss9001 Date: Tue, 23 Nov 2021 14:39:48 +0200 Subject: [PATCH 53/57] Update rpc_client.hpp Minor changes --- .../graphene/peerplays_sidechain/common/rpc_client.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index a83f9531..ecb14b13 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -6,7 +6,7 @@ #include #include -#include +//#include namespace graphene { namespace peerplays_sidechain { @@ -93,7 +93,7 @@ private: friend class detail::http_call_impl; friend detail::tcp_socket; friend detail::ssl_socket; - static constexpr auto response_size_limit_bytes = 1024 * 1024 * 1024; + 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; -- 2.45.2 From ce216b4646c31fa7c2c53411c25f12e3ff0aa43e Mon Sep 17 00:00:00 2001 From: moss9001 Date: Fri, 26 Nov 2021 14:43:05 +0200 Subject: [PATCH 54/57] Minor updates Main change: config parameters: instead of "hive-node-ip" and "hive-node-rpc-port" single parameter "hive-node-rpc-url" is implemented --- .../peerplays_sidechain/common/rpc_client.cpp | 21 ++++++++++----- .../peerplays_sidechain/common/rpc_client.hpp | 4 ++- .../sidechain_net_handler_hive.hpp | 5 ++-- .../peerplays_sidechain_plugin.cpp | 4 +-- .../sidechain_net_handler_hive.cpp | 26 ++++++++----------- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index a2a84997..d3aa0f82 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -712,7 +712,17 @@ http_call::http_call(const url_data &url, const std::string &method, const std:: m_context = 0; } - set_port(url.port); + if (url.port) + m_port_default = url.port; + else { + if (url.schema_type == url_schema_type::https) + m_port_default = https_port; + else + m_port_default = http_port; + } + + m_port = m_port_default; + set_path(url.path); try { @@ -765,10 +775,10 @@ uint16_t http_call::port() const { } void http_call::set_port(uint16_t port) { - if (port == 0) - m_port = is_ssl() ? https_port : http_port; - else + if (port) m_port = port; + else + m_port = m_port_default; } bool http_call::exec(const http_request &request, http_response *response) { @@ -812,7 +822,7 @@ void http_call::ctor_priv() { namespace graphene { namespace peerplays_sidechain { -rpc_client::rpc_client(const std::string &url, uint16_t port, const std::string &user_name, const std::string &password, bool debug) : +rpc_client::rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug) : debug_rpc_calls(debug), request_id(0), client(url) @@ -821,7 +831,6 @@ rpc_client::rpc_client(const std::string &url, uint16_t port, const std::string client.set_method("POST"); client.set_headers("Authorization : Basic" + fc::base64_encode(user_name + ":" + password)); - client.set_port(port); } std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) { diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp index ecb14b13..63d218ee 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -31,6 +31,7 @@ struct url_data { schema_type(url_schema_type::unknown), port(0) { } + url_data(const std::string &url); void clear(); @@ -97,6 +98,7 @@ private: 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; @@ -116,7 +118,7 @@ namespace graphene { namespace peerplays_sidechain { class rpc_client { public: - rpc_client(const std::string &url, uint16_t port, const std::string &user_name, const std::string &password, bool debug); + rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug); protected: std::string retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index 675c3cdd..a6851a5a 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -14,7 +14,7 @@ namespace graphene { namespace peerplays_sidechain { class hive_node_rpc_client : public rpc_client { public: - hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls); + hive_node_rpc_client(const std::string & url, const std::string & user_name, const std::string & password, 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); @@ -48,8 +48,7 @@ public: bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); private: - std::string node_ip; - uint32_t node_rpc_port; + std::string node_rpc_url; std::string node_rpc_user; std::string node_rpc_password; hive_node_rpc_client *node_rpc_client; diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 02a046fc..f9433971 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -156,8 +156,8 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options( "Tuple of [Bitcoin public key, Bitcoin private key] (may specify multiple times)"); cli.add_options()("hive-sidechain-enabled", bpo::value()->default_value(false), "Hive sidechain handler enabled"); - cli.add_options()("hive-node-ip", bpo::value()->default_value("127.0.0.1"), "Hive node IP address"); - cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "Hive node RPC port"); + cli.add_options()("hive-node-rpc-url", bpo::value()->default_value("127.0.0.1"), "Hive node URL (http(s)://host:port/)"); + //cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "Deprecated: Hive node RPC port. See: hive-node-rpc-url"); cli.add_options()("hive-node-rpc-user", bpo::value(), "Hive node RPC user"); cli.add_options()("hive-node-rpc-password", bpo::value(), "Hive node RPC password"); cli.add_options()("hive-private-key", bpo::value>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4", "5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n")), diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index fdde2376..999bf7b2 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -32,8 +32,8 @@ namespace graphene { namespace peerplays_sidechain { -hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : - rpc_client(_ip, _port, _user, _password, _debug_rpc_calls) { +hive_node_rpc_client::hive_node_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 hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { @@ -122,19 +122,14 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi debug_rpc_calls = options.at("debug-rpc-calls").as(); } - if ((options.count("hive-node-url") > 0) && (options.count("hive-node-ip") > 0)) - FC_THROW("both keys are present: hive-node-url and hive-node-ip"); + if (options.count("hive-node-rpc-url")) + node_rpc_url = options.at("hive-node-rpc-url").as(); - if (options.count("hive-node-ip")) - node_ip = options.at("hive-node-ip").as(); +// if (options.count("hive-node-rpc-port")) +// node_rpc_port = options.at("hive-node-rpc-port").as(); +// else +// node_rpc_port = 0; - if (options.count("hive-node-url")) - node_ip = options.at("hive-node-url").as(); - - if (options.count("hive-node-rpc-port")) - node_rpc_port = options.at("hive-node-rpc-port").as(); - else - node_rpc_port = 0; if (options.count("hive-node-rpc-user")) { node_rpc_user = options.at("hive-node-rpc-user").as(); } else { @@ -158,11 +153,12 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi } } - node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); + node_rpc_client = new hive_node_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(); if (chain_id_str.empty()) { - elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); +// elog("No Hive node running at ${url} or wrong rpc port: ${port}", ("url", node_rpc_url)("port", node_rpc_port)); + elog("No Hive node running at ${url}", ("url", node_rpc_url)); FC_ASSERT(false); } chain_id = chain_id_type(chain_id_str); -- 2.45.2 From 9cc4557e8a565389b9974110707cef88cf6d4b76 Mon Sep 17 00:00:00 2001 From: moss9001 Date: Fri, 26 Nov 2021 14:44:55 +0200 Subject: [PATCH 55/57] Clang formatted --- .../peerplays_sidechain/common/rpc_client.cpp | 16 ++++++++-------- .../sidechain_net_handler_hive.hpp | 2 +- .../sidechain_net_handler_hive.cpp | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp index d3aa0f82..70723f0e 100644 --- a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -712,14 +712,14 @@ http_call::http_call(const url_data &url, const std::string &method, const std:: m_context = 0; } - if (url.port) - m_port_default = url.port; - else { - if (url.schema_type == url_schema_type::https) - m_port_default = https_port; - else - m_port_default = http_port; - } + if (url.port) + m_port_default = url.port; + else { + if (url.schema_type == url_schema_type::https) + m_port_default = https_port; + else + m_port_default = http_port; + } m_port = m_port_default; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp index a6851a5a..47e6bf90 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -14,7 +14,7 @@ namespace graphene { namespace peerplays_sidechain { class hive_node_rpc_client : public rpc_client { public: - hive_node_rpc_client(const std::string & url, const std::string & user_name, const std::string & password, bool debug_rpc_calls); + hive_node_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, 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); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp index 999bf7b2..02287a95 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -32,7 +32,7 @@ namespace graphene { namespace peerplays_sidechain { -hive_node_rpc_client::hive_node_rpc_client(const std::string & url, const std::string & user_name, const std::string & password, bool debug_rpc_calls) : +hive_node_rpc_client::hive_node_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) { } @@ -125,10 +125,10 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi if (options.count("hive-node-rpc-url")) node_rpc_url = options.at("hive-node-rpc-url").as(); -// if (options.count("hive-node-rpc-port")) -// node_rpc_port = options.at("hive-node-rpc-port").as(); -// else -// node_rpc_port = 0; + // if (options.count("hive-node-rpc-port")) + // node_rpc_port = options.at("hive-node-rpc-port").as(); + // else + // node_rpc_port = 0; if (options.count("hive-node-rpc-user")) { node_rpc_user = options.at("hive-node-rpc-user").as(); @@ -157,7 +157,7 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi std::string chain_id_str = node_rpc_client->get_chain_id(); if (chain_id_str.empty()) { -// elog("No Hive node running at ${url} or wrong rpc port: ${port}", ("url", node_rpc_url)("port", node_rpc_port)); + // elog("No Hive node running at ${url} or wrong rpc port: ${port}", ("url", node_rpc_url)("port", node_rpc_port)); elog("No Hive node running at ${url}", ("url", node_rpc_url)); FC_ASSERT(false); } -- 2.45.2 From 25866711ca1e57667e08ecb86a1936418fbea80a Mon Sep 17 00:00:00 2001 From: moss9001 Date: Fri, 26 Nov 2021 19:22:48 +0200 Subject: [PATCH 56/57] BTC event handler synchronized Sync object (mutex) added to sidechain_net_handler_bitcoin::handle_event --- .../sidechain_net_handler_bitcoin.hpp | 5 +++++ .../sidechain_net_handler_bitcoin.cpp | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index dd6ebb28..171d4bdf 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -7,6 +7,8 @@ #include +#include + #include #include @@ -114,6 +116,9 @@ private: fc::future on_changed_objects_task; bitcoin::bitcoin_address::network network_type; + std::mutex event_handler_mutex; + typedef std::lock_guard scoped_lock; + std::string create_primary_wallet_address(const std::vector &son_pubkeys); std::string create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index ca4e9149..e4b03a49 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1801,10 +1801,12 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) { std::string block = bitcoin_client->getblock(event_data); - if (block != "") { - const auto &vins = extract_info_from_block(block); + if (block.empty()) + return; - const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); + auto vins = extract_info_from_block(block); + scoped_lock interlock(event_handler_mutex); + const auto & sidechain_addresses_idx = database.get_index_type().indices().get(); for (const auto &v : vins) { // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT @@ -1833,7 +1835,7 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount); sidechain_event_data_received(sed); } - } + } std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(const std::string &user_address) { -- 2.45.2 From d0a54c48a0aa2fb2561742e752cc4ea2b5132021 Mon Sep 17 00:00:00 2001 From: moss9001 Date: Fri, 26 Nov 2021 19:24:19 +0200 Subject: [PATCH 57/57] Clang formatted --- .../sidechain_net_handler_bitcoin.hpp | 4 +- .../sidechain_net_handler_bitcoin.cpp | 61 +++++++++---------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index 171d4bdf..9b08bc15 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -116,8 +116,8 @@ private: fc::future on_changed_objects_task; bitcoin::bitcoin_address::network network_type; - std::mutex event_handler_mutex; - typedef std::lock_guard scoped_lock; + std::mutex event_handler_mutex; + typedef std::lock_guard scoped_lock; std::string create_primary_wallet_address(const std::vector &son_pubkeys); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index e4b03a49..940977e4 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -1801,41 +1801,40 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) { std::string block = bitcoin_client->getblock(event_data); - if (block.empty()) - return; + if (block.empty()) + return; - auto vins = extract_info_from_block(block); - scoped_lock interlock(event_handler_mutex); - const auto & sidechain_addresses_idx = database.get_index_type().indices().get(); + auto vins = extract_info_from_block(block); + scoped_lock interlock(event_handler_mutex); + const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - for (const auto &v : vins) { - // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address, time_point_sec::maximum())); - if (addr_itr == sidechain_addresses_idx.end()) - continue; + for (const auto &v : vins) { + // !!! EXTRACT DEPOSIT ADDRESS FROM SIDECHAIN ADDRESS OBJECT + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, v.address, time_point_sec::maximum())); + if (addr_itr == sidechain_addresses_idx.end()) + continue; - std::stringstream ss; - ss << "bitcoin" - << "-" << v.out.hash_tx << "-" << v.out.n_vout; - 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 = addr_itr->sidechain; - sed.sidechain_uid = sidechain_uid; - sed.sidechain_transaction_id = v.out.hash_tx; - sed.sidechain_from = v.address; - sed.sidechain_to = ""; - sed.sidechain_currency = "BTC"; - sed.sidechain_amount = v.out.amount; - sed.peerplays_from = addr_itr->sidechain_address_account; - sed.peerplays_to = database.get_global_properties().parameters.son_account(); - price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; - sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount); - sidechain_event_data_received(sed); - } + std::stringstream ss; + ss << "bitcoin" + << "-" << v.out.hash_tx << "-" << v.out.n_vout; + 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 = addr_itr->sidechain; + sed.sidechain_uid = sidechain_uid; + sed.sidechain_transaction_id = v.out.hash_tx; + sed.sidechain_from = v.address; + sed.sidechain_to = ""; + sed.sidechain_currency = "BTC"; + sed.sidechain_amount = v.out.amount; + sed.peerplays_from = addr_itr->sidechain_address_account; + sed.peerplays_to = database.get_global_properties().parameters.son_account(); + price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount); + sidechain_event_data_received(sed); + } } std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(const std::string &user_address) { -- 2.45.2