From 6aee0c6f82261e56596bcf09633df6618ef02584 Mon Sep 17 00:00:00 2001 From: hirunda Date: Fri, 9 Sep 2022 00:07:53 +0200 Subject: [PATCH] Moving json transaction parsing Moving json transaction parsing in getrawtransaction and forming btc_tx object --- .../peerplays_sidechain/CMakeLists.txt | 2 +- .../bitcoin/libbitcoin_client.cpp | 48 +++--- .../bitcoin/libbitcoin_client.hpp | 3 +- .../sidechain_net_handler_bitcoin.hpp | 30 +++- .../sidechain_net_handler_bitcoin.cpp | 157 +++++++++--------- 5 files changed, 132 insertions(+), 108 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 326cff88..91df0828 100644 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -37,7 +37,7 @@ endif() unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS) unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE) -target_link_libraries( peerplays_sidechain PRIVATE curl graphene_plugin zmq bitcoin-system bitcoin-network bitcoin-client ) +target_link_libraries( peerplays_sidechain PRIVATE curl graphene_plugin zmq bitcoin-system bitcoin-protocol bitcoin-client bitcoin-explorer ) target_include_directories( peerplays_sidechain PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp b/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp index fc985fca..5adb1228 100644 --- a/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp @@ -4,6 +4,10 @@ #include #include +#include + +#include +#include namespace graphene { namespace peerplays_sidechain { @@ -21,39 +25,37 @@ libbitcoin_client::libbitcoin_client() : } void libbitcoin_client::send_transaction(std::string tx) { - // std::cout<<"Enter in function"< libbitcoin_client::list_unspent(std::string add std::vector result; auto error_handler = [&](const std::error_code &ec) { - std::cout << "Error code: " << ec << std::endl; + elog("error on list_unspent ${error_code}", ("error_code", ec.message())); }; auto replay_handler = [&](const libbitcoin::chain::points_value &points) { diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp index d0a1fa70..2d0260de 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp @@ -13,9 +13,8 @@ struct list_unspent_replay { class libbitcoin_client { public: libbitcoin_client(); - // test methods for libbitcoin void send_transaction(std::string tx); - void fetch_trx_by_address(std::string address, double amount); + void get_transaction (std::string tx_id); std::vector list_unspent(std::string address, double amount); private: 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 7c5c854f..fc9bbf2e 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,8 +1,8 @@ #pragma once -#include #include #include +#include #include #include @@ -24,6 +24,20 @@ public: uint64_t amount_; }; +class btc_txin { +public: + std::vector tx_address; + uint64_t tx_amount; + uint64_t tx_vout; +}; + +class btc_tx { +public: + std::string tx_txid; + uint32_t tx_confirmations; + std::vector tx_in_list; +}; + class bitcoin_client { public: enum class multi_type { @@ -44,8 +58,8 @@ public: virtual uint64_t estimatesmartfee(uint16_t conf_target = 128) = 0; virtual std::string getblock(const std::string &block_hash, int32_t verbosity = 2) = 0; - virtual std::string getrawtransaction(const std::string &txid, const bool verbose = false) = 0; - virtual std::string getnetworkinfo() = 0; + virtual btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) = 0; + virtual void getnetworkinfo() = 0; virtual std::string getblockchaininfo() = 0; virtual std::vector listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) = 0; virtual std::string sendrawtransaction(const std::string &tx_hex) = 0; @@ -58,8 +72,8 @@ public: uint64_t estimatesmartfee(uint16_t conf_target = 128); std::string getblock(const std::string &block_hash, int32_t verbosity = 2); - std::string getrawtransaction(const std::string &txid, const bool verbose = false); - std::string getnetworkinfo(); + btc_tx getrawtransaction(const std::string &txid, const bool verbose = false); + void getnetworkinfo(); std::string getblockchaininfo(); void importmulti(const std::vector &address_or_script_array, const bool rescan = true); std::vector listunspent(const uint32_t minconf = 1, const uint32_t maxconf = 9999999); @@ -75,14 +89,15 @@ private: std::string password; std::string wallet; std::string wallet_password; + uint32_t bitcoin_major_version; }; class bitcoin_libbitcoin_client : public bitcoin_client, public libbitcoin_client { public: uint64_t estimatesmartfee(uint16_t conf_target = 128); std::string getblock(const std::string &block_hash, int32_t verbosity = 2); - std::string getrawtransaction(const std::string &txid, const bool verbose = false); - std::string getnetworkinfo(); + btc_tx getrawtransaction(const std::string &txid, const bool verbose = false); + void getnetworkinfo(); std::string getblockchaininfo(); std::vector listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999); std::string sendrawtransaction(const std::string &tx_hex); @@ -132,7 +147,6 @@ private: std::string ip; uint32_t zmq_port; uint32_t rpc_port; - uint32_t bitcoin_major_version; std::string rpc_user; std::string rpc_password; std::string wallet; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 186ccdf9..e5b094b4 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -59,16 +59,58 @@ std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t return str; } -std::string bitcoin_rpc_client::getnetworkinfo() { +void bitcoin_rpc_client::getnetworkinfo() { std::string params = std::string("[]"); std::string str = send_post_request("getnetworkinfo", params, debug_rpc_calls); - return str; + + std::stringstream network_info_ss(str); + boost::property_tree::ptree network_info_json; + boost::property_tree::read_json(network_info_ss, network_info_json); + + bitcoin_major_version = network_info_json.get("result.version") / 10000; + ilog("Bitcoin major version is: '${version}'", ("version", bitcoin_major_version)); } -std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { +btc_tx bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { std::string params = std::string("[\"") + txid + std::string("\",") + (verbose ? "true" : "false") + std::string("]"); std::string str = send_post_request("getrawtransaction", params, debug_rpc_calls); - return str; + + btc_tx tx; + + std::stringstream tx_ss(str); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(tx_ss, tx_json); + + if (tx_json.count("error") && tx_json.get_child("error").empty()) { + + std::string tx_txid = tx_json.get("result.txid"); + uint32_t tx_confirmations = tx_json.get("result.confirmations"); + + tx.tx_txid = tx_txid; + tx.tx_confirmations = tx_confirmations; + + for (auto &input : tx_json.get_child("result.vout")) { + btc_txin tx_in; + std::string tx_vout_s = input.second.get("n"); + tx_in.tx_vout = std::stoll(tx_vout_s); + if (bitcoin_major_version > 21) { + std::string address = input.second.get("scriptPubKey.address"); + tx_in.tx_address.emplace_back(address); + } else { + for (auto &address : input.second.get_child("scriptPubKey.addresses")) { + tx_in.tx_address.emplace_back(address.second.data()); + } + } + + std::string tx_amount_s = input.second.get("value"); + tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); + tx_in.tx_amount = std::stoll(tx_amount_s); + + tx.tx_in_list.emplace_back(tx_in); + } + } + + return tx; } std::string bitcoin_rpc_client::getblockchaininfo() { @@ -213,6 +255,8 @@ std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) { } return json.get("result"); + std::cout << "Result of transaction: " << std::endl; + std::cout << ss.str() << std::endl; } return str; @@ -255,14 +299,14 @@ std::string bitcoin_libbitcoin_client::getblock(const std::string &block_hash, i return std::string(""); } -std::string bitcoin_libbitcoin_client::getrawtransaction(const std::string &txid, const bool verbose) { +btc_tx bitcoin_libbitcoin_client::getrawtransaction(const std::string &txid, const bool verbose) { // TODO - return std::string(""); + btc_tx tx; + return tx; } -std::string bitcoin_libbitcoin_client::getnetworkinfo() { +void bitcoin_libbitcoin_client::getnetworkinfo() { // TODO - return std::string(""); } std::string bitcoin_libbitcoin_client::getblockchaininfo() { @@ -435,13 +479,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain } } - std::string network_info_str = bitcoin_client->getnetworkinfo(); - std::stringstream network_info_ss(network_info_str); - boost::property_tree::ptree network_info_json; - boost::property_tree::read_json(network_info_ss, network_info_json); - - bitcoin_major_version = network_info_json.get("result.version") / 10000; - ilog("Bitcoin major version is: '${version}'", ("version", bitcoin_major_version)); + bitcoin_client->getnetworkinfo(); listener = std::unique_ptr(new zmq_listener(ip, zmq_port)); listener->start(); @@ -577,39 +615,28 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) 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)); - std::string tx_str = bitcoin_client->getrawtransaction(swdo_txid, true); - std::stringstream tx_ss(tx_str); - boost::property_tree::ptree tx_json; - boost::property_tree::read_json(tx_ss, tx_json); + btc_tx tx = bitcoin_client->getrawtransaction(swdo_txid, true); + // lib_bitcoin_client->get_transaction(swdo_txid); - if (tx_json.count("error") && tx_json.get_child("error").empty()) { + if (!tx.tx_in_list.empty()) { - std::string tx_txid = tx_json.get("result.txid"); - uint32_t tx_confirmations = tx_json.get("result.confirmations"); + std::string tx_txid = tx.tx_txid; + uint32_t tx_confirmations = tx.tx_confirmations; std::string tx_address = ""; uint64_t tx_amount = -1; uint64_t tx_vout = -1; - for (auto &input : tx_json.get_child("result.vout")) { - std::string tx_vout_s = input.second.get("n"); - tx_vout = std::stoll(tx_vout_s); + for (auto &input : tx.tx_in_list) { + tx_vout = input.tx_vout; if (tx_vout == swdo_vout) { - if (bitcoin_major_version > 21) { - std::string address = input.second.get("scriptPubKey.address"); + for (auto &address : input.tx_address) { if (address == swdo_address) { tx_address = address; - } - } else { - for (auto &address : input.second.get_child("scriptPubKey.addresses")) { - if (address.second.data() == swdo_address) { - tx_address = address.second.data(); - break; - } + break; } } - std::string tx_amount_s = input.second.get("value"); - tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); - tx_amount = std::stoll(tx_amount_s); + + tx_amount = input.tx_amount; break; } } @@ -992,12 +1019,9 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain return false; } - std::string tx_str = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true); - std::stringstream tx_ss(tx_str); - boost::property_tree::ptree tx_json; - boost::property_tree::read_json(tx_ss, tx_json); + btc_tx tx = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true); - if ((tx_json.count("error")) && (!tx_json.get_child("error").empty())) { + if (tx.tx_in_list.empty()) { return false; } @@ -1017,29 +1041,18 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address); - std::string tx_txid = tx_json.get("result.txid"); - uint32_t tx_confirmations = tx_json.get("result.confirmations"); + std::string tx_txid = tx.tx_txid; + uint32_t tx_confirmations = tx.tx_confirmations; std::string tx_address = addr.get_address(); int64_t tx_amount = -1; if (tx_confirmations >= gpo.parameters.son_bitcoin_min_tx_confirmations()) { if (sto.object_id.is()) { - for (auto &input : tx_json.get_child("result.vout")) { - if (bitcoin_major_version > 21) { - std::string address = input.second.get("scriptPubKey.address"); + for (auto &input : tx.tx_in_list) { + for (auto &address : input.tx_address) { if (address == tx_address) { - std::string tx_amount_s = input.second.get("value"); - tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); - tx_amount = std::stoll(tx_amount_s); - } - } else { - for (auto &address : input.second.get_child("scriptPubKey.addresses")) { - if (address.second.data() == tx_address) { - std::string tx_amount_s = input.second.get("value"); - tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); - tx_amount = std::stoll(tx_amount_s); - break; - } + tx_amount = input.tx_amount; + break; } } } @@ -1321,8 +1334,9 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran std::string final_tx_hex = fc::to_hex(pack(tx)); std::string res = bitcoin_client->sendrawtransaction(final_tx_hex); + // lib_bitcoin_client->send_transaction(final_tx_hex); - return res; + return tx.get_txid().str(); } void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) { @@ -1413,16 +1427,19 @@ std::vector sidechain_net_handler_bitcoin::extract_info_from_block for (const auto &o : tx.get_child("vout")) { const auto script = o.second.get_child("scriptPubKey"); + std::vector address_list; - if (bitcoin_major_version > 21) { - if (!script.count("address")) - continue; + if (script.count("address")) { + address_list.emplace_back(script.get("address")); + } else if (script.count("addresses")) { + for (const auto &addr : script.get_child("addresses")) { + address_list.emplace_back(addr.second.get_value()); + } } else { - if (!script.count("addresses")) - continue; + continue; } - auto sort_out_vin = [&](std::string address) { + for (auto &address : address_list) { const auto address_base58 = address; info_for_vin vin; vin.out.hash_tx = tx.get_child("txid").get_value(); @@ -1432,14 +1449,6 @@ std::vector sidechain_net_handler_bitcoin::extract_info_from_block vin.out.n_vout = o.second.get_child("n").get_value(); vin.address = address_base58; result.push_back(vin); - }; - - if (bitcoin_major_version > 21) { - std::string address = script.get("address"); - sort_out_vin(address); - } else { - for (const auto &addr : script.get_child("addresses")) // in which cases there can be more addresses? - sort_out_vin(addr.second.get_value()); } } }