#461 - handle exception when execute POST request

This commit is contained in:
Vlad Dobromyslov 2022-10-18 10:19:03 +03:00
parent 71c113c190
commit 283fbd28f7
4 changed files with 223 additions and 188 deletions

View file

@ -62,47 +62,67 @@ rpc_client::rpc_client(std::string _url, std::string _user, std::string _passwor
} }
std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) { 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); if (reply_str.empty()) {
boost::property_tree::ptree json; wlog("RPC call ${function}, empty reply string", ("function", __FUNCTION__));
boost::property_tree::read_json(ss, json);
if (json.find("result") == json.not_found()) {
return ""; return "";
} }
auto json_result = json.get_child_optional("result"); try {
if (json_result) { std::stringstream ss(reply_str);
boost::property_tree::ptree array_ptree = json_result.get(); boost::property_tree::ptree json;
if (!array_path.empty()) { boost::property_tree::read_json(ss, json);
array_ptree = json_result.get().get_child(array_path); if (json.find("result") == json.not_found()) {
return "";
} }
uint32_t array_el_idx = -1;
for (const auto &array_el : array_ptree) { auto json_result = json.get_child_optional("result");
array_el_idx = array_el_idx + 1; if (json_result) {
if (array_el_idx == idx) { boost::property_tree::ptree array_ptree = json_result.get();
std::stringstream ss_res; if (!array_path.empty()) {
boost::property_tree::json_parser::write_json(ss_res, array_el.second); array_ptree = json_result.get().get_child(array_path);
return ss_res.str(); }
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();
}
} }
} }
} catch (const boost::property_tree::json_parser::json_parser_error &e) {
wlog("RPC call ${function} failed: ${e}", ("function", __FUNCTION__)("e", e.what()));
} }
return ""; return "";
} }
std::string rpc_client::retrieve_value_from_reply(std::string reply_str, std::string value_path) { std::string rpc_client::retrieve_value_from_reply(std::string reply_str, std::string value_path) {
std::stringstream ss(reply_str); if (reply_str.empty()) {
boost::property_tree::ptree json; wlog("RPC call ${function}, empty reply string", ("function", __FUNCTION__));
boost::property_tree::read_json(ss, json);
if (json.find("result") == json.not_found()) {
return ""; return "";
} }
auto json_result = json.get_child_optional("result"); try {
if (json_result) { std::stringstream ss(reply_str);
return json_result.get().get<std::string>(value_path); 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_optional("result");
if (json_result) {
return json_result.get().get<std::string>(value_path);
}
return json.get<std::string>("result");
} catch (const boost::property_tree::json_parser::json_parser_error &e) {
wlog("RPC call ${function} failed: ${e}", ("function", __FUNCTION__)("e", e.what()));
} }
return json.get<std::string>("result"); return "";
} }
std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log) { std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log) {
@ -118,23 +138,27 @@ std::string rpc_client::send_post_request(std::string method, std::string params
body << " }"; body << " }";
const auto reply = send_post_request(body.str(), show_log); try {
const auto reply = send_post_request(body.str(), show_log);
if (reply.body.empty()) { if (reply.body.empty()) {
wlog("RPC call ${function} failed", ("function", __FUNCTION__)); wlog("RPC call ${function} failed", ("function", __FUNCTION__));
return ""; return "";
} }
std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
boost::property_tree::ptree json; boost::property_tree::ptree json;
boost::property_tree::read_json(ss, json); boost::property_tree::read_json(ss, json);
if (json.count("error") && !json.get_child("error").empty()) { 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())); wlog("RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body.str())("msg", ss.str()));
} }
if (reply.status == 200) { if (reply.status == 200) {
return ss.str(); return ss.str();
}
} catch (const boost::system::system_error &e) {
elog("RPC call ${function} failed: ${e}", ("function", __FUNCTION__)("e", e.what()));
} }
return ""; return "";

View file

@ -30,14 +30,13 @@ bitcoin_rpc_client::bitcoin_rpc_client(std::string _url, std::string _user, std:
} }
std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) { std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) {
std::string params = std::string("[\"") + wallet_name + std::string("\"]"); const std::string params = std::string("[\"") + wallet_name + std::string("\"]");
std::string str = send_post_request("createwallet", params, debug_rpc_calls); return send_post_request("createwallet", params, debug_rpc_calls);
return str;
} }
uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) { uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
std::string params = std::string("[") + std::to_string(conf_target) + std::string("]"); const std::string params = std::string("[") + std::to_string(conf_target) + std::string("]");
std::string str = send_post_request("estimatesmartfee", params, debug_rpc_calls); const std::string str = send_post_request("estimatesmartfee", params, debug_rpc_calls);
if (str.length() == 0) { if (str.length() == 0) {
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
@ -60,26 +59,23 @@ uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
} }
std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) { std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) {
std::string params = std::string("[\"") + block_hash + std::string("\",") + std::to_string(verbosity) + std::string("]"); const std::string params = std::string("[\"") + block_hash + std::string("\",") + std::to_string(verbosity) + std::string("]");
std::string str = send_post_request("getblock", params, debug_rpc_calls); return send_post_request("getblock", params, debug_rpc_calls);
return str;
} }
std::string bitcoin_rpc_client::getnetworkinfo() { std::string bitcoin_rpc_client::getnetworkinfo() {
std::string params = std::string("[]"); static const std::string params = std::string("[]");
std::string str = send_post_request("getnetworkinfo", params, debug_rpc_calls); return send_post_request("getnetworkinfo", params, debug_rpc_calls);
return str;
} }
std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) {
std::string params = std::string("[\"") + txid + std::string("\",") + (verbose ? "true" : "false") + std::string("]"); const 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 send_post_request("getrawtransaction", params, debug_rpc_calls);
return str;
} }
std::string bitcoin_rpc_client::getblockchaininfo() { std::string bitcoin_rpc_client::getblockchaininfo() {
std::string params = std::string("[]"); static const std::string params = std::string("[]");
std::string str = send_post_request("getblockchaininfo", params, debug_rpc_calls); const std::string str = send_post_request("getblockchaininfo", params, debug_rpc_calls);
if (str.length() > 0) { if (str.length() > 0) {
@ -130,8 +126,8 @@ void bitcoin_rpc_client::importmulti(const std::vector<multi_params> &address_or
std::vector<btc_txout> bitcoin_rpc_client::listunspent(const uint32_t minconf, const uint32_t maxconf) { std::vector<btc_txout> bitcoin_rpc_client::listunspent(const uint32_t minconf, const uint32_t maxconf) {
std::vector<btc_txout> result; std::vector<btc_txout> result;
std::string params = std::string("[") + std::to_string(minconf) + "," + std::to_string(maxconf) + std::string("]"); const std::string params = std::string("[") + std::to_string(minconf) + "," + std::to_string(maxconf) + std::string("]");
std::string str = send_post_request("listunspent", params, debug_rpc_calls); const std::string str = send_post_request("listunspent", params, debug_rpc_calls);
if (str.length() == 0) { if (str.length() == 0) {
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
@ -167,7 +163,7 @@ std::vector<btc_txout> bitcoin_rpc_client::listunspent_by_address_and_amount(con
params += std::string("} ]"); params += std::string("} ]");
std::vector<btc_txout> result; std::vector<btc_txout> result;
std::string str = send_post_request("listunspent", params, debug_rpc_calls); const std::string str = send_post_request("listunspent", params, debug_rpc_calls);
if (str.length() == 0) { if (str.length() == 0) {
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
@ -194,16 +190,13 @@ std::vector<btc_txout> bitcoin_rpc_client::listunspent_by_address_and_amount(con
} }
std::string bitcoin_rpc_client::loadwallet(const std::string &filename) { std::string bitcoin_rpc_client::loadwallet(const std::string &filename) {
const std::string params = std::string("[\"") + filename + std::string("\"]");
std::string params = std::string("[\"") + filename + std::string("\"]"); return send_post_request("loadwallet", params, debug_rpc_calls);
std::string str = send_post_request("loadwallet", params, debug_rpc_calls);
return str;
} }
std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) { std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) {
const std::string params = std::string("[\"") + tx_hex + std::string("\"]");
std::string params = std::string("[\"") + tx_hex + std::string("\"]"); const std::string str = send_post_request("sendrawtransaction", params, debug_rpc_calls);
std::string str = send_post_request("sendrawtransaction", params, debug_rpc_calls);
if (str.length() > 0) { if (str.length() > 0) {
std::stringstream ss(str); std::stringstream ss(str);
@ -225,8 +218,8 @@ std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) {
} }
std::string bitcoin_rpc_client::walletlock() { std::string bitcoin_rpc_client::walletlock() {
std::string params = std::string("[]"); static const std::string params = std::string("[]");
std::string str = send_post_request("walletlock", params, debug_rpc_calls); const std::string str = send_post_request("walletlock", params, debug_rpc_calls);
if (str.length() == 0) { if (str.length() == 0) {
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
@ -243,8 +236,8 @@ std::string bitcoin_rpc_client::walletlock() {
} }
bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) { bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) {
std::string params = std::string("[\"") + passphrase + std::string("\",") + std::to_string(timeout) + std::string("]"); const std::string params = std::string("[\"") + passphrase + std::string("\",") + std::to_string(timeout) + std::string("]");
std::string str = send_post_request("walletpassphrase", params, debug_rpc_calls); const std::string str = send_post_request("walletpassphrase", params, debug_rpc_calls);
if (str.length() == 0) if (str.length() == 0)
return false; return false;
else else
@ -366,6 +359,10 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
} }
std::string blockchain_info = bitcoin_client->getblockchaininfo(); std::string blockchain_info = bitcoin_client->getblockchaininfo();
if (blockchain_info.empty()) {
elog("No Bitcoin node running at ${url}", ("url", url));
FC_ASSERT(false);
}
std::stringstream bci_ss(std::string(blockchain_info.begin(), blockchain_info.end())); std::stringstream bci_ss(std::string(blockchain_info.begin(), blockchain_info.end()));
boost::property_tree::ptree bci_json; boost::property_tree::ptree bci_json;
boost::property_tree::read_json(bci_ss, bci_json); boost::property_tree::read_json(bci_ss, bci_json);
@ -385,6 +382,10 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
} }
std::string network_info_str = bitcoin_client->getnetworkinfo(); std::string network_info_str = bitcoin_client->getnetworkinfo();
if (network_info_str.empty()) {
elog("No Bitcoin node running at ${url}", ("url", url));
FC_ASSERT(false);
}
std::stringstream network_info_ss(network_info_str); std::stringstream network_info_ss(network_info_str);
boost::property_tree::ptree network_info_json; boost::property_tree::ptree network_info_json;
boost::property_tree::read_json(network_info_ss, network_info_json); boost::property_tree::read_json(network_info_ss, network_info_json);
@ -526,48 +527,50 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
uint64_t swdo_amount = swdo->sidechain_amount.value; 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)); 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); const std::string tx_str = bitcoin_client->getrawtransaction(swdo_txid, true);
std::stringstream tx_ss(tx_str); if (tx_str != "") {
boost::property_tree::ptree tx_json; std::stringstream tx_ss(tx_str);
boost::property_tree::read_json(tx_ss, tx_json); 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()) { if (tx_json.count("error") && tx_json.get_child("error").empty()) {
std::string tx_txid = tx_json.get<std::string>("result.txid"); std::string tx_txid = tx_json.get<std::string>("result.txid");
uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations"); uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations");
std::string tx_address = ""; std::string tx_address = "";
uint64_t tx_amount = -1; uint64_t tx_amount = -1;
uint64_t tx_vout = -1; uint64_t tx_vout = -1;
for (auto &input : tx_json.get_child("result.vout")) { for (auto &input : tx_json.get_child("result.vout")) {
std::string tx_vout_s = input.second.get<std::string>("n"); std::string tx_vout_s = input.second.get<std::string>("n");
tx_vout = std::stoll(tx_vout_s); tx_vout = std::stoll(tx_vout_s);
if (tx_vout == swdo_vout) { if (tx_vout == swdo_vout) {
if (bitcoin_major_version > 21) { if (bitcoin_major_version > 21) {
std::string address = input.second.get<std::string>("scriptPubKey.address"); std::string address = input.second.get<std::string>("scriptPubKey.address");
if (address == swdo_address) { if (address == swdo_address) {
tx_address = address; tx_address = address;
} }
} else { } else {
for (auto &address : input.second.get_child("scriptPubKey.addresses")) { for (auto &address : input.second.get_child("scriptPubKey.addresses")) {
if (address.second.data() == swdo_address) { if (address.second.data() == swdo_address) {
tx_address = address.second.data(); tx_address = address.second.data();
break; break;
}
} }
} }
std::string tx_amount_s = input.second.get<std::string>("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;
} }
std::string tx_amount_s = input.second.get<std::string>("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;
} }
}
process_ok = (swdo_txid == tx_txid) && process_ok = (swdo_txid == tx_txid) &&
(swdo_address == tx_address) && (swdo_address == tx_address) &&
(swdo_amount == tx_amount) && (swdo_amount == tx_amount) &&
(swdo_vout == tx_vout) && (swdo_vout == tx_vout) &&
(gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations); (gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations);
}
} }
object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id; object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
@ -936,59 +939,61 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
return false; return false;
} }
std::string tx_str = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true); const std::string tx_str = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true);
std::stringstream tx_ss(tx_str); if (tx_str != "") {
boost::property_tree::ptree tx_json; std::stringstream tx_ss(tx_str);
boost::property_tree::read_json(tx_ss, tx_json); 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())) { if ((tx_json.count("error")) && (!tx_json.get_child("error").empty())) {
return false; return false;
} }
const chain::global_property_object &gpo = database.get_global_properties(); const chain::global_property_object &gpo = database.get_global_properties();
using namespace bitcoin; using namespace bitcoin;
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights; std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
for (auto si : sto.signers) { for (auto si : sto.signers) {
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(si.public_key))); auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(si.public_key)));
pubkey_weights.push_back(std::make_pair(pub_key, si.weight)); pubkey_weights.push_back(std::make_pair(pub_key, si.weight));
} }
btc_weighted_multisig_address addr(pubkey_weights, network_type); btc_weighted_multisig_address addr(pubkey_weights, network_type);
std::string tx_txid = tx_json.get<std::string>("result.txid"); std::string tx_txid = tx_json.get<std::string>("result.txid");
uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations"); uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations");
std::string tx_address = addr.get_address(); std::string tx_address = addr.get_address();
int64_t tx_amount = -1; int64_t tx_amount = -1;
if (tx_confirmations >= gpo.parameters.son_bitcoin_min_tx_confirmations()) { if (tx_confirmations >= gpo.parameters.son_bitcoin_min_tx_confirmations()) {
if (sto.object_id.is<son_wallet_deposit_id_type>()) { if (sto.object_id.is<son_wallet_deposit_id_type>()) {
for (auto &input : tx_json.get_child("result.vout")) { for (auto &input : tx_json.get_child("result.vout")) {
if (bitcoin_major_version > 21) { if (bitcoin_major_version > 21) {
std::string address = input.second.get<std::string>("scriptPubKey.address"); std::string address = input.second.get<std::string>("scriptPubKey.address");
if (address == tx_address) { if (address == tx_address) {
std::string tx_amount_s = input.second.get<std::string>("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<std::string>("value"); std::string tx_amount_s = input.second.get<std::string>("value");
tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); 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 = 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<std::string>("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;
}
} }
} }
} }
settle_amount = asset(tx_amount, database.get_global_properties().parameters.btc_asset());
return true;
} }
settle_amount = asset(tx_amount, database.get_global_properties().parameters.btc_asset());
return true;
}
if (sto.object_id.is<son_wallet_withdraw_id_type>()) { if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
auto swwo = database.get<son_wallet_withdraw_object>(sto.object_id); auto swwo = database.get<son_wallet_withdraw_object>(sto.object_id);
settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.btc_asset()); settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.btc_asset());
return true; return true;
}
} }
} }
return false; return false;
@ -1038,11 +1043,11 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
} }
uint64_t fee_rate = bitcoin_client->estimatesmartfee(); uint64_t fee_rate = bitcoin_client->estimatesmartfee();
uint64_t min_fee_rate = 1000; const uint64_t min_fee_rate = 1000;
fee_rate = std::max(fee_rate, min_fee_rate); fee_rate = std::max(fee_rate, min_fee_rate);
uint64_t total_amount = 0.0; uint64_t total_amount = 0.0;
std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(prev_pw_address, 0); const std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(prev_pw_address, 0);
if (inputs.size() == 0) { if (inputs.size() == 0) {
elog("Failed to find UTXOs to spend for ${pw}", ("pw", prev_pw_address)); elog("Failed to find UTXOs to spend for ${pw}", ("pw", prev_pw_address));
@ -1085,7 +1090,7 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_
std::string nvout = suid.substr(suid.find_last_of("-") + 1); std::string nvout = suid.substr(suid.find_last_of("-") + 1);
uint64_t deposit_amount = swdo.sidechain_amount.value; uint64_t deposit_amount = swdo.sidechain_amount.value;
uint64_t fee_rate = bitcoin_client->estimatesmartfee(); uint64_t fee_rate = bitcoin_client->estimatesmartfee();
uint64_t min_fee_rate = 1000; const uint64_t min_fee_rate = 1000;
fee_rate = std::max(fee_rate, min_fee_rate); fee_rate = std::max(fee_rate, min_fee_rate);
if (fee_rate >= deposit_amount) { if (fee_rate >= deposit_amount) {
@ -1128,11 +1133,11 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s
std::string redeem_script = json.get<std::string>("redeemScript"); std::string redeem_script = json.get<std::string>("redeemScript");
int64_t fee_rate = bitcoin_client->estimatesmartfee(); int64_t fee_rate = bitcoin_client->estimatesmartfee();
int64_t min_fee_rate = 1000; const int64_t min_fee_rate = 1000;
fee_rate = std::max(fee_rate, min_fee_rate); fee_rate = std::max(fee_rate, min_fee_rate);
int64_t total_amount = 0; int64_t total_amount = 0;
std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0); const std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0);
if (inputs.size() == 0) { if (inputs.size() == 0) {
elog("Failed to find UTXOs to spend for ${pw}", ("pw", pw_address)); elog("Failed to find UTXOs to spend for ${pw}", ("pw", pw_address));
@ -1240,14 +1245,11 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
// Add redeemscripts to vins and make tx ready for sending // Add redeemscripts to vins and make tx ready for sending
sign_witness_transaction_finalize(tx, redeem_scripts, false); sign_witness_transaction_finalize(tx, redeem_scripts, false);
std::string final_tx_hex = fc::to_hex(pack(tx)); std::string final_tx_hex = fc::to_hex(pack(tx));
std::string res = bitcoin_client->sendrawtransaction(final_tx_hex); return bitcoin_client->sendrawtransaction(final_tx_hex);
return res;
} }
void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) { void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) {
const std::string block = bitcoin_client->getblock(event_data);
std::string block = bitcoin_client->getblock(event_data);
if (block.empty()) if (block.empty())
return; return;

View file

@ -33,13 +33,13 @@ std::string ethereum_rpc_client::admin_node_info() {
} }
std::string ethereum_rpc_client::eth_get_block_by_number(std::string block_number, bool full_block) { std::string ethereum_rpc_client::eth_get_block_by_number(std::string block_number, bool full_block) {
std::string params = "[ \"" + block_number + "\", " + (full_block ? "true" : "false") + "]"; const std::string params = "[ \"" + block_number + "\", " + (full_block ? "true" : "false") + "]";
return send_post_request("eth_getBlockByNumber", params, debug_rpc_calls); return send_post_request("eth_getBlockByNumber", params, debug_rpc_calls);
} }
std::string ethereum_rpc_client::eth_get_logs(std::string wallet_contract_address) { std::string ethereum_rpc_client::eth_get_logs(std::string wallet_contract_address) {
std::string params = "[{\"address\": \"" + wallet_contract_address + "\"}]"; const std::string params = "[{\"address\": \"" + wallet_contract_address + "\"}]";
std::string reply_str = send_post_request("eth_getLogs", params, debug_rpc_calls); const std::string reply_str = send_post_request("eth_getLogs", params, debug_rpc_calls);
return retrieve_value_from_reply(reply_str, ""); return retrieve_value_from_reply(reply_str, "");
} }
@ -56,28 +56,32 @@ std::string ethereum_rpc_client::eth_gas_price() {
} }
std::string ethereum_rpc_client::get_chain_id() { std::string ethereum_rpc_client::get_chain_id() {
std::string reply_str = net_version(); const std::string reply_str = net_version();
return retrieve_value_from_reply(reply_str, ""); return retrieve_value_from_reply(reply_str, "");
} }
std::string ethereum_rpc_client::get_network_id() { std::string ethereum_rpc_client::get_network_id() {
std::string reply_str = admin_node_info(); const std::string reply_str = admin_node_info();
return retrieve_value_from_reply(reply_str, "protocols.eth.network"); return retrieve_value_from_reply(reply_str, "protocols.eth.network");
} }
std::string ethereum_rpc_client::get_nonce(const std::string &address) { std::string ethereum_rpc_client::get_nonce(const std::string &address) {
std::string reply_str = eth_get_transaction_count("[\"" + address + "\", \"latest\"]"); const std::string reply_str = eth_get_transaction_count("[\"" + address + "\", \"latest\"]");
const auto nonce_val = ethereum::from_hex<boost::multiprecision::uint256_t>(retrieve_value_from_reply(reply_str, "")); const auto nonce_string = retrieve_value_from_reply(reply_str, "");
return nonce_val == 0 ? ethereum::add_0x("0") : ethereum::add_0x(ethereum::to_hex(nonce_val)); if (!nonce_string.empty()) {
const auto nonce_val = ethereum::from_hex<boost::multiprecision::uint256_t>(nonce_string);
return nonce_val == 0 ? ethereum::add_0x("0") : ethereum::add_0x(ethereum::to_hex(nonce_val));
}
return "";
} }
std::string ethereum_rpc_client::get_gas_price() { std::string ethereum_rpc_client::get_gas_price() {
std::string reply_str = eth_gas_price(); const std::string reply_str = eth_gas_price();
return retrieve_value_from_reply(reply_str, ""); return retrieve_value_from_reply(reply_str, "");
} }
std::string ethereum_rpc_client::get_gas_limit() { std::string ethereum_rpc_client::get_gas_limit() {
std::string reply_str = eth_get_block_by_number("latest", false); const std::string reply_str = eth_get_block_by_number("latest", false);
if (!reply_str.empty()) { if (!reply_str.empty()) {
std::stringstream ss(reply_str); std::stringstream ss(reply_str);
boost::property_tree::ptree json; boost::property_tree::ptree json;
@ -138,13 +142,18 @@ sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidecha
rpc_client = new ethereum_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls); rpc_client = new ethereum_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls);
std::string chain_id_str = rpc_client->get_chain_id(); const std::string chain_id_str = rpc_client->get_chain_id();
if (chain_id_str.empty()) { if (chain_id_str.empty()) {
elog("No Ethereum node running at ${url}", ("url", rpc_url)); elog("No Ethereum node running at ${url}", ("url", rpc_url));
FC_ASSERT(false); FC_ASSERT(false);
} }
chain_id = std::stoll(chain_id_str); chain_id = std::stoll(chain_id_str);
std::string network_id_str = rpc_client->get_network_id();
const std::string network_id_str = rpc_client->get_network_id();
if (network_id_str.empty()) {
elog("No Ethereum node running at ${url}", ("url", rpc_url));
FC_ASSERT(false);
}
network_id = std::stoll(network_id_str); network_id = std::stoll(network_id_str);
ilog("Running on Ethereum network, chain id ${chain_id_str}, network id ${network_id_str}", ("chain_id_str", chain_id_str)("network_id_str", network_id_str)); ilog("Running on Ethereum network, chain id ${chain_id_str}, network id ${network_id_str}", ("chain_id_str", chain_id_str)("network_id_str", network_id_str));
@ -678,7 +687,7 @@ void sidechain_net_handler_ethereum::schedule_ethereum_listener() {
void sidechain_net_handler_ethereum::ethereum_listener_loop() { void sidechain_net_handler_ethereum::ethereum_listener_loop() {
schedule_ethereum_listener(); schedule_ethereum_listener();
std::string reply = rpc_client->eth_get_block_by_number("latest", false); const std::string reply = rpc_client->eth_get_block_by_number("latest", false);
//std::string reply = rpc_client->eth_get_logs(wallet_contract_address); //std::string reply = rpc_client->eth_get_logs(wallet_contract_address);
if (!reply.empty()) { if (!reply.empty()) {
std::stringstream ss(reply); std::stringstream ss(reply);
@ -697,7 +706,7 @@ void sidechain_net_handler_ethereum::ethereum_listener_loop() {
} }
void sidechain_net_handler_ethereum::handle_event(const std::string &event_data) { void sidechain_net_handler_ethereum::handle_event(const std::string &event_data) {
std::string block = rpc_client->eth_get_block_by_number("latest", true); const std::string block = rpc_client->eth_get_block_by_number("latest", true);
if (block != "") { if (block != "") {
add_to_son_listener_log("BLOCK : " + event_data); add_to_son_listener_log("BLOCK : " + event_data);
std::stringstream ss(block); std::stringstream ss(block);

View file

@ -35,12 +35,12 @@ hive_rpc_client::hive_rpc_client(const std::string &url, const std::string &user
} }
std::string hive_rpc_client::account_history_api_get_transaction(std::string transaction_id) { std::string hive_rpc_client::account_history_api_get_transaction(std::string transaction_id) {
std::string params = "{ \"id\": \"" + transaction_id + "\" }"; const std::string params = "{ \"id\": \"" + transaction_id + "\" }";
return send_post_request("account_history_api.get_transaction", params, debug_rpc_calls); return send_post_request("account_history_api.get_transaction", params, debug_rpc_calls);
} }
std::string hive_rpc_client::block_api_get_block(uint32_t block_number) { std::string hive_rpc_client::block_api_get_block(uint32_t block_number) {
std::string params = "{ \"block_num\": " + std::to_string(block_number) + " }"; const std::string params = "{ \"block_num\": " + std::to_string(block_number) + " }";
return send_post_request("block_api.get_block", params, debug_rpc_calls); return send_post_request("block_api.get_block", params, debug_rpc_calls);
} }
@ -57,7 +57,7 @@ std::string hive_rpc_client::condenser_api_get_accounts(std::vector<std::string>
} }
std::string hive_rpc_client::condenser_api_get_config() { std::string hive_rpc_client::condenser_api_get_config() {
std::string params = "[]"; static const std::string params = "[]";
return send_post_request("condenser_api.get_config", params, debug_rpc_calls); return send_post_request("condenser_api.get_config", params, debug_rpc_calls);
} }
@ -70,7 +70,7 @@ std::string hive_rpc_client::database_api_get_version() {
} }
std::string hive_rpc_client::network_broadcast_api_broadcast_transaction(std::string htrx) { std::string hive_rpc_client::network_broadcast_api_broadcast_transaction(std::string htrx) {
std::string params = "{ \"trx\": " + htrx + ", \"max_block_age\": -1 }"; const std::string params = "{ \"trx\": " + htrx + ", \"max_block_age\": -1 }";
return send_post_request("network_broadcast_api.broadcast_transaction", params, debug_rpc_calls); return send_post_request("network_broadcast_api.broadcast_transaction", params, debug_rpc_calls);
} }
@ -88,27 +88,27 @@ std::string hive_rpc_client::get_account_memo_key(std::string account) {
} }
std::string hive_rpc_client::get_chain_id() { std::string hive_rpc_client::get_chain_id() {
std::string reply_str = database_api_get_version(); const std::string reply_str = database_api_get_version();
return retrieve_value_from_reply(reply_str, "chain_id"); return retrieve_value_from_reply(reply_str, "chain_id");
} }
std::string hive_rpc_client::get_head_block_id() { std::string hive_rpc_client::get_head_block_id() {
std::string reply_str = database_api_get_dynamic_global_properties(); const std::string reply_str = database_api_get_dynamic_global_properties();
return retrieve_value_from_reply(reply_str, "head_block_id"); return retrieve_value_from_reply(reply_str, "head_block_id");
} }
std::string hive_rpc_client::get_head_block_time() { std::string hive_rpc_client::get_head_block_time() {
std::string reply_str = database_api_get_dynamic_global_properties(); const std::string reply_str = database_api_get_dynamic_global_properties();
return retrieve_value_from_reply(reply_str, "time"); return retrieve_value_from_reply(reply_str, "time");
} }
std::string hive_rpc_client::get_is_test_net() { std::string hive_rpc_client::get_is_test_net() {
std::string reply_str = condenser_api_get_config(); const std::string reply_str = condenser_api_get_config();
return retrieve_value_from_reply(reply_str, "IS_TEST_NET"); return retrieve_value_from_reply(reply_str, "IS_TEST_NET");
} }
std::string hive_rpc_client::get_last_irreversible_block_num() { std::string hive_rpc_client::get_last_irreversible_block_num() {
std::string reply_str = database_api_get_dynamic_global_properties(); const std::string reply_str = database_api_get_dynamic_global_properties();
return retrieve_value_from_reply(reply_str, "last_irreversible_block_num"); return retrieve_value_from_reply(reply_str, "last_irreversible_block_num");
} }
@ -148,14 +148,14 @@ sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugi
rpc_client = new hive_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls); rpc_client = new hive_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls);
std::string chain_id_str = rpc_client->get_chain_id(); const std::string chain_id_str = rpc_client->get_chain_id();
if (chain_id_str.empty()) { if (chain_id_str.empty()) {
elog("No Hive node running at ${url}", ("url", rpc_url)); elog("No Hive node running at ${url}", ("url", rpc_url));
FC_ASSERT(false); FC_ASSERT(false);
} }
chain_id = chain_id_type(chain_id_str); chain_id = chain_id_type(chain_id_str);
std::string is_test_net = rpc_client->get_is_test_net(); const std::string is_test_net = rpc_client->get_is_test_net();
network_type = is_test_net.compare("true") == 0 ? hive::network::testnet : hive::network::mainnet; network_type = is_test_net.compare("true") == 0 ? hive::network::testnet : hive::network::mainnet;
if (network_type == 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)); ilog("Running on Hive mainnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str));
@ -254,7 +254,7 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) {
account_auths[wallet_son.public_key] = wallet_son.weight; account_auths[wallet_son.public_key] = wallet_son.weight;
} }
std::string memo_key = rpc_client->get_account_memo_key(wallet_account_name); const std::string memo_key = rpc_client->get_account_memo_key(wallet_account_name);
hive::authority active; hive::authority active;
active.weight_threshold = total_weight * 2 / 3 + 1; active.weight_threshold = total_weight * 2 / 3 + 1;
@ -303,7 +303,7 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) {
uint64_t swdo_sidechain_amount = swdo->sidechain_amount.value; 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("-"))); uint64_t swdo_op_idx = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-")));
std::string tx_str = rpc_client->account_history_api_get_transaction(swdo_txid); const std::string tx_str = rpc_client->account_history_api_get_transaction(swdo_txid);
if (tx_str != "") { if (tx_str != "") {
std::stringstream ss_tx(tx_str); std::stringstream ss_tx(tx_str);
@ -495,7 +495,7 @@ void sidechain_net_handler_hive::process_primary_wallet() {
account_auths[active_son.public_key] = active_son.weight; account_auths[active_son.public_key] = active_son.weight;
} }
std::string memo_key = rpc_client->get_account_memo_key(wallet_account_name); const std::string memo_key = rpc_client->get_account_memo_key(wallet_account_name);
if (memo_key.empty()) { if (memo_key.empty()) {
return; return;
@ -510,10 +510,10 @@ void sidechain_net_handler_hive::process_primary_wallet() {
auo.active = active; auo.active = active;
auo.memo_key = hive::public_key_type(memo_key); auo.memo_key = hive::public_key_type(memo_key);
std::string block_id_str = rpc_client->get_head_block_id(); const std::string block_id_str = rpc_client->get_head_block_id();
hive::block_id_type head_block_id(block_id_str); hive::block_id_type head_block_id(block_id_str);
std::string head_block_time_str = rpc_client->get_head_block_time(); const std::string head_block_time_str = 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(head_block_time_str);
hive::signed_transaction htrx; hive::signed_transaction htrx;
@ -668,10 +668,10 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob
t_op.amount.symbol = symbol; t_op.amount.symbol = symbol;
t_op.memo = ""; t_op.memo = "";
std::string block_id_str = rpc_client->get_head_block_id(); const std::string block_id_str = rpc_client->get_head_block_id();
hive::block_id_type head_block_id(block_id_str); hive::block_id_type head_block_id(block_id_str);
std::string head_block_time_str = rpc_client->get_head_block_time(); const std::string head_block_time_str = 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(head_block_time_str);
hive::signed_transaction htrx; hive::signed_transaction htrx;
@ -727,7 +727,7 @@ std::string sidechain_net_handler_hive::process_sidechain_transaction(const side
hive::signed_transaction htrx; hive::signed_transaction htrx;
fc::raw::unpack(ss_trx, htrx, 1000); fc::raw::unpack(ss_trx, htrx, 1000);
std::string chain_id_str = rpc_client->get_chain_id(); const std::string chain_id_str = rpc_client->get_chain_id();
const hive::chain_id_type chain_id(chain_id_str); const hive::chain_id_type chain_id(chain_id_str);
fc::optional<fc::ecc::private_key> privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object(sidechain).sidechain_public_keys.at(sidechain))); fc::optional<fc::ecc::private_key> privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object(sidechain).sidechain_public_keys.at(sidechain)));
@ -770,7 +770,7 @@ bool sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_tr
return false; return false;
} }
std::string tx_str = rpc_client->account_history_api_get_transaction(sto.sidechain_transaction); const std::string tx_str = rpc_client->account_history_api_get_transaction(sto.sidechain_transaction);
if (tx_str != "") { if (tx_str != "") {
std::stringstream ss_tx(tx_str); std::stringstream ss_tx(tx_str);
@ -781,7 +781,7 @@ bool sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_tr
std::string tx_txid = tx_json.get<std::string>("result.transaction_id"); std::string tx_txid = tx_json.get<std::string>("result.transaction_id");
uint32_t tx_block_num = tx_json.get<uint32_t>("result.block_num"); uint32_t tx_block_num = tx_json.get<uint32_t>("result.block_num");
uint32_t last_irreversible_block = std::stoul(rpc_client->get_last_irreversible_block_num()); const uint32_t last_irreversible_block = std::stoul(rpc_client->get_last_irreversible_block_num());
//std::string tx_address = addr.get_address(); //std::string tx_address = addr.get_address();
//int64_t tx_amount = -1; //int64_t tx_amount = -1;
@ -817,7 +817,7 @@ void sidechain_net_handler_hive::schedule_hive_listener() {
void sidechain_net_handler_hive::hive_listener_loop() { void sidechain_net_handler_hive::hive_listener_loop() {
schedule_hive_listener(); schedule_hive_listener();
std::string reply = rpc_client->database_api_get_dynamic_global_properties(); const std::string reply = rpc_client->database_api_get_dynamic_global_properties();
if (!reply.empty()) { if (!reply.empty()) {
std::stringstream ss(reply); std::stringstream ss(reply);
boost::property_tree::ptree json; boost::property_tree::ptree json;
@ -844,7 +844,7 @@ void sidechain_net_handler_hive::hive_listener_loop() {
} }
void sidechain_net_handler_hive::handle_event(const std::string &event_data) { 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())); const std::string block = rpc_client->block_api_get_block(std::atoll(event_data.c_str()));
if (block != "") { if (block != "") {
add_to_son_listener_log("BLOCK : " + event_data); add_to_son_listener_log("BLOCK : " + event_data);
std::stringstream ss(block); std::stringstream ss(block);