From d07c343be604a4f64690e56a9cdfece86a28faf4 Mon Sep 17 00:00:00 2001 From: Davor Hirunda Date: Wed, 23 Mar 2022 17:37:32 +0000 Subject: [PATCH] Support parsing addresses for bitcoin v21 and v22 --- .../sidechain_net_handler_bitcoin.hpp | 2 + .../sidechain_net_handler_bitcoin.cpp | 85 ++++++++++++++++--- 2 files changed, 76 insertions(+), 11 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 f2577a28..0c6a5cc7 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 @@ -56,6 +56,7 @@ public: std::string getaddressinfo(const std::string &address); 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(); std::string gettransaction(const std::string &txid, const bool include_watch_only = false); std::string getblockchaininfo(); void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false); @@ -123,6 +124,7 @@ 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 e011a6d6..8b3f3736 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -461,6 +461,32 @@ std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t return ""; } +std::string bitcoin_rpc_client::getnetworkinfo() { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getnetworkinfo\", \"method\": " + "\"getnetworkinfo\", \"params\": [] }"); + + const auto reply = send_post_request(body, debug_rpc_calls); + + if (reply.body.empty()) { + wlog("Bitcoin 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("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str())); + } + + return ""; +} + std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getrawtransaction\", \"method\": " "\"getrawtransaction\", \"params\": ["); @@ -1017,6 +1043,14 @@ 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)); + listener = std::unique_ptr(new zmq_listener(ip, zmq_port)); listener->event_received.connect([this](const std::string &event_data) { std::thread(&sidechain_net_handler_bitcoin::handle_event, this, event_data).detach(); @@ -1167,10 +1201,17 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) std::string tx_vout_s = input.second.get("n"); tx_vout = std::stoll(tx_vout_s); if (tx_vout == swdo_vout) { - for (auto &address : input.second.get_child("scriptPubKey.addresses")) { - if (address.second.data() == swdo_address) { - tx_address = address.second.data(); - break; + if (bitcoin_major_version > 21) { + std::string address = input.second.get("scriptPubKey.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; + } } } std::string tx_amount_s = input.second.get("value"); @@ -1582,12 +1623,21 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain if (tx_confirmations >= gpo.parameters.son_bitcoin_min_tx_confirmations()) { if (sto.object_id.is()) { for (auto &input : tx_json.get_child("result.vout")) { - for (auto &address : input.second.get_child("scriptPubKey.addresses")) { - if (address.second.data() == tx_address) { + if (bitcoin_major_version > 21) { + std::string address = input.second.get("scriptPubKey.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); - break; + } + } 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; + } } } } @@ -1926,11 +1976,16 @@ 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"); - if (!script.count("addresses")) - continue; + if (bitcoin_major_version > 21) { + if (!script.count("address")) + continue; + } else { + if (!script.count("addresses")) + continue; + } - for (const auto &addr : script.get_child("addresses")) { // in which cases there can be more addresses? - const auto address_base58 = addr.second.get_value(); + auto sort_out_vin = [&](std::string address) { + const auto address_base58 = address; info_for_vin vin; vin.out.hash_tx = tx.get_child("txid").get_value(); string amount = o.second.get_child("value").get_value(); @@ -1939,6 +1994,14 @@ 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()); } } }