diff --git a/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp b/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp index 4ddbd7ce..146444b4 100644 --- a/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace graphene { namespace chain { @@ -15,7 +16,7 @@ namespace graphene { namespace chain { sidechain_type sidechain; object_id_type object_id; std::string transaction; - std::vector signers; + std::vector signers; account_id_type fee_payer()const { return payer; } share_type calculate_fee(const fee_parameters_type& k)const { return 0; } @@ -29,8 +30,7 @@ namespace graphene { namespace chain { account_id_type payer; sidechain_transaction_id_type sidechain_transaction_id; - std::string transaction; - block_id_type block; + std::string signature; bool complete; account_id_type fee_payer()const { return payer; } @@ -45,6 +45,7 @@ namespace graphene { namespace chain { account_id_type payer; sidechain_transaction_id_type sidechain_transaction_id; + std::string sidechain_transaction; account_id_type fee_payer()const { return payer; } share_type calculate_fee( const fee_parameters_type& k )const { return 0; } @@ -62,10 +63,10 @@ FC_REFLECT( graphene::chain::sidechain_transaction_create_operation, (fee)(payer FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation, (fee)(payer) (sidechain_transaction_id) - (transaction) - (block) + (signature) (complete) ) FC_REFLECT( graphene::chain::sidechain_transaction_send_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::sidechain_transaction_send_operation, (fee)(payer) - (sidechain_transaction_id) ) \ No newline at end of file + (sidechain_transaction_id) + (sidechain_transaction) ) diff --git a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp index f4f596cf..d3fbe1b3 100644 --- a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp @@ -20,9 +20,13 @@ namespace graphene { namespace chain { sidechain_type sidechain; object_id_type object_id; std::string transaction; - std::vector> signers; + std::vector signers; + std::vector> signatures; + std::string sidechain_transaction; - block_id_type block; + uint32_t total_weight = 0; + uint32_t current_weight = 0; + uint32_t threshold = 0; bool valid = false; bool complete = false; bool sent = false; @@ -63,7 +67,11 @@ FC_REFLECT_DERIVED( graphene::chain::sidechain_transaction_object, (graphene::db (object_id) (transaction) (signers) - (block) + (signatures) + (sidechain_transaction) + (total_weight) + (current_weight) + (threshold) (valid) (complete) (sent) ) diff --git a/libraries/chain/sidechain_transaction_evaluator.cpp b/libraries/chain/sidechain_transaction_evaluator.cpp index 3c72b9e9..ab6e69a8 100644 --- a/libraries/chain/sidechain_transaction_evaluator.cpp +++ b/libraries/chain/sidechain_transaction_evaluator.cpp @@ -20,6 +20,7 @@ void_result sidechain_transaction_create_evaluator::do_evaluate(const sidechain_ FC_ASSERT(sto_obj == sto_idx.end(), "Sidechain transaction for a given object is already created"); FC_ASSERT(!op.transaction.empty(), "Sidechain transaction data not set"); + FC_ASSERT(op.signers.size() > 0, "Sidechain transaction signers not set"); return void_result(); } FC_CAPTURE_AND_RETHROW( ( op ) ) } @@ -30,10 +31,16 @@ object_id_type sidechain_transaction_create_evaluator::do_apply(const sidechain_ sto.sidechain = op.sidechain; sto.object_id = op.object_id; sto.transaction = op.transaction; - std::transform(op.signers.begin(), op.signers.end(), std::inserter(sto.signers, sto.signers.end()), [](const son_id_type son_id) { - return std::make_pair(son_id, false); + sto.signers = op.signers; + std::transform(op.signers.begin(), op.signers.end(), std::inserter(sto.signatures, sto.signatures.end()), [](const son_info &si) { + return std::make_pair(si.son_id, std::string()); }); - sto.block = db().head_block_id(); + for (const auto &si : op.signers) { + sto.total_weight = sto.total_weight + si.total_votes; + } + sto.sidechain_transaction = ""; + sto.current_weight = 0; + sto.threshold = sto.total_weight * 2 / 3 + 1; sto.valid = true; sto.complete = false; sto.sent = false; @@ -54,15 +61,13 @@ void_result sidechain_transaction_sign_evaluator::do_evaluate(const sidechain_tr FC_ASSERT(son_obj != son_idx.end(), "SON object not found"); bool expected = false; - for (auto signer : sto_obj->signers) { - if (signer.first == son_obj->id) { - expected = !signer.second; + for (auto signature : sto_obj->signatures) { + if (signature.first == son_obj->id) { + expected = signature.second.empty(); } } FC_ASSERT(expected, "Signer not expected"); - FC_ASSERT(sto_obj->block == op.block, "Sidechain transaction already signed in this block"); - FC_ASSERT(sto_obj->valid, "Transaction not valid"); FC_ASSERT(!sto_obj->complete, "Transaction signing completed"); FC_ASSERT(!sto_obj->sent, "Transaction already sent"); @@ -79,14 +84,17 @@ object_id_type sidechain_transaction_sign_evaluator::do_apply(const sidechain_tr auto son_obj = son_idx.find(op.payer); db().modify(*sto_obj, [&](sidechain_transaction_object &sto) { - sto.transaction = op.transaction; - sto.block = db().head_block_id(); - sto.complete = op.complete; - for (size_t i = 0; i < sto.signers.size(); i++) { - if (sto.signers.at(i).first == son_obj->id) { - sto.signers.at(i).second = true; - } + for (size_t i = 0; i < sto.signatures.size(); i++) { + if (sto.signatures.at(i).first == son_obj->id) { + sto.signatures.at(i).second = op.signature; + } } + for (size_t i = 0; i < sto.signers.size(); i++) { + if (sto.signers.at(i).son_id == son_obj->id) { + sto.current_weight = sto.current_weight + sto.signers.at(i).total_votes; + } + } + sto.complete = op.complete; }); db().modify(son_obj->statistics(db()), [&](son_statistics_object& sso) { @@ -117,7 +125,7 @@ object_id_type sidechain_transaction_send_evaluator::do_apply(const sidechain_tr auto sto_obj = sto_idx.find(op.sidechain_transaction_id); db().modify(*sto_obj, [&](sidechain_transaction_object &sto) { - sto.block = db().head_block_id(); + sto.sidechain_transaction = op.sidechain_transaction; sto.sent = true; }); 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 5814b208..60582de6 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 @@ -35,7 +35,7 @@ public: virtual bool process_deposit(const son_wallet_deposit_object &swdo) = 0; virtual bool process_withdrawal(const son_wallet_withdraw_object &swwo) = 0; virtual std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete) = 0; - virtual bool send_sidechain_transaction(const sidechain_transaction_object &sto) = 0; + virtual bool send_sidechain_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction) = 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 637a5254..62363b15 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 @@ -22,6 +22,7 @@ public: bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password); std::string addmultisigaddress(const uint32_t nrequired, const std::vector public_keys); + std::string combinepsbt(const vector &psbts); std::string createpsbt(const std::vector &ins, const fc::flat_map outs); std::string createrawtransaction(const std::vector &ins, const fc::flat_map outs); std::string createwallet(const std::string &wallet_name); @@ -86,7 +87,7 @@ public: 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, bool &complete); - bool send_sidechain_transaction(const sidechain_transaction_object &sto); + bool send_sidechain_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction); private: std::string ip; @@ -103,16 +104,19 @@ private: fc::future on_changed_objects_task; std::string create_transaction(const std::vector &inputs, const fc::flat_map outputs); - std::string sign_transaction(const std::string &tx, bool &complete); - bool send_transaction(const std::string &tx); + std::string sign_transaction(const sidechain_transaction_object &sto, bool &complete); + bool send_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction); std::string create_transaction_raw(const std::vector &inputs, const fc::flat_map outputs); std::string create_transaction_psbt(const std::vector &inputs, const fc::flat_map outputs); std::string create_transaction_standalone(const std::vector &inputs, const fc::flat_map outputs); - std::string sign_transaction_raw(const std::string &tx, bool &complete); - std::string sign_transaction_psbt(const std::string &tx, bool &complete); - std::string sign_transaction_standalone(const std::string &tx, bool &complete); + std::string sign_transaction_raw(const sidechain_transaction_object &sto, bool &complete); + std::string sign_transaction_psbt(const sidechain_transaction_object &sto, bool &complete); + std::string sign_transaction_standalone(const sidechain_transaction_object &sto, bool &complete); + + bool send_transaction_raw(const sidechain_transaction_object &sto, std::string &sidechain_transaction); + bool send_transaction_psbt(const sidechain_transaction_object &sto, std::string &sidechain_transaction); void handle_event(const std::string &event_data); std::vector extract_info_from_block(const std::string &_block); 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 157dc421..c2245c6f 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 @@ -17,7 +17,7 @@ public: 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, bool &complete); - bool send_sidechain_transaction(const sidechain_transaction_object &sto); + bool send_sidechain_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction); private: void on_applied_block(const signed_block &b); diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index deda02b3..75a89870 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -352,8 +352,9 @@ void peerplays_sidechain_plugin_impl::son_processing() { // Tasks that are executed by all active SONs, no matter if scheduled // E.g. sending approvals and signing (only signing that can be done in parallel) approve_proposals(); + process_sidechain_transactions(); - // Tasks that are executed by scheduled and active SON + // Tasks that are executed by scheduled and active SON only if (current_son_id == scheduled_son_id) { create_son_down_proposals(); @@ -375,6 +376,8 @@ void peerplays_sidechain_plugin_impl::son_processing() { // E.g. sending approvals and signing that SON was required to do while it was active //approve_leftover_proposals(); ??? //process_leftover_sidechain_transactions(); ??? + approve_proposals(); + process_sidechain_transactions(); } } } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index c6eccd12..31b5da39 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -258,8 +258,7 @@ void sidechain_net_handler::process_sidechain_transactions() { sidechain_transaction_sign_operation sts_op; sts_op.payer = plugin.get_current_son_object().son_account; sts_op.sidechain_transaction_id = sto.id; - sts_op.transaction = processed_sidechain_tx; - sts_op.block = sto.block; + sts_op.signature = processed_sidechain_tx; sts_op.complete = complete; signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), sts_op); @@ -281,7 +280,8 @@ void sidechain_net_handler::send_sidechain_transactions() { std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) { ilog("Sidechain transaction to send: ${sto}", ("sto", sto)); - bool sent = send_sidechain_transaction(sto); + std::string sidechain_transaction = ""; + bool sent = send_sidechain_transaction(sto, sidechain_transaction); if (!sent) { wlog("Sidechain transaction not sent: ${sto}", ("sto", sto)); @@ -291,6 +291,7 @@ void sidechain_net_handler::send_sidechain_transactions() { sidechain_transaction_send_operation sts_op; sts_op.payer = plugin.get_current_son_object().son_account; sts_op.sidechain_transaction_id = sto.id; + sts_op.sidechain_transaction = sidechain_transaction; signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), sts_op); trx.validate(); @@ -320,7 +321,7 @@ std::string sidechain_net_handler::process_sidechain_transaction(const sidechain FC_ASSERT(false, "process_sidechain_transaction not implemented"); } -bool sidechain_net_handler::send_sidechain_transaction(const sidechain_transaction_object &sto) { +bool sidechain_net_handler::send_sidechain_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { FC_ASSERT(false, "send_sidechain_transaction not implemented"); } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index a788b04f..cc23610d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -45,7 +45,7 @@ std::string bitcoin_rpc_client::addmultisigaddress(const uint32_t nrequired, con params = params + pubkeys + std::string("]"); body = body + params + std::string("] }"); - const auto reply = send_post_request(body, true); + const auto reply = send_post_request(body); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -66,6 +66,40 @@ std::string bitcoin_rpc_client::addmultisigaddress(const uint32_t nrequired, con return ""; } +std::string bitcoin_rpc_client::combinepsbt(const vector &psbts) { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"combinepsbt\", \"method\": " + "\"combinepsbt\", \"params\": [["); + std::string params = ""; + for (std::string psbt : psbts) { + if (!params.empty()) { + params = params + ","; + } + params = params + std::string("\"") + psbt + std::string("\""); + } + body = body + params + std::string("]] }"); + const auto reply = send_post_request(body); + + 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) { + std::stringstream ss; + boost::property_tree::json_parser::write_json(ss, json); + 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::createpsbt(const std::vector &ins, const fc::flat_map outs) { std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"createpsbt\", " "\"method\": \"createpsbt\", \"params\": ["); @@ -87,7 +121,7 @@ std::string bitcoin_rpc_client::createpsbt(const std::vector &ins, co } body += std::string("]] }"); - const auto reply = send_post_request(body, true); + const auto reply = send_post_request(body); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -131,7 +165,7 @@ std::string bitcoin_rpc_client::createrawtransaction(const std::vectorsons; - std::vector signers; - for (const son_info &si : signer_sons) { - signers.push_back(si.son_id); - } - 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 = signers; + stc_op.signers = prev_sw->sons; proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; @@ -977,18 +1005,12 @@ bool sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_obj if (!tx_str.empty()) { const chain::global_property_object &gpo = database.get_global_properties(); - auto active_sons = gpo.active_sons; - std::vector signers; - for (const son_info &si : active_sons) { - signers.push_back(si.son_id); - } - 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 = signers; + stc_op.signers = gpo.active_sons; proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; @@ -1059,18 +1081,12 @@ bool sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw if (!tx_str.empty()) { const chain::global_property_object &gpo = database.get_global_properties(); - auto active_sons = gpo.active_sons; - std::vector signers; - for (const son_info &si : active_sons) { - signers.push_back(si.son_id); - } - 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 = signers; + stc_op.signers = gpo.active_sons; proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; @@ -1094,6 +1110,7 @@ bool sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw } std::string sidechain_net_handler_bitcoin::process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete) { + complete = false; //// Uncomment to get signing in order from sto.signers //son_id_type invalid_signer = son_id_type(0xFFFFFFFF); @@ -1109,11 +1126,13 @@ std::string sidechain_net_handler_bitcoin::process_sidechain_transaction(const s // return ""; //} - return sign_transaction(sto.transaction, complete); + return sign_transaction(sto, complete); } -bool sidechain_net_handler_bitcoin::send_sidechain_transaction(const sidechain_transaction_object &sto) { - return send_transaction(sto.transaction); +bool sidechain_net_handler_bitcoin::send_sidechain_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { + sidechain_transaction = ""; + + return send_transaction(sto, sidechain_transaction); } // Creates transaction in any format @@ -1128,16 +1147,19 @@ std::string sidechain_net_handler_bitcoin::create_transaction(const std::vector< // Adds signature to transaction // Function to actually add signature should return transaction with added signature string, or empty string in case of failure -std::string sidechain_net_handler_bitcoin::sign_transaction(const std::string &tx_str, bool &complete) { +std::string sidechain_net_handler_bitcoin::sign_transaction(const sidechain_transaction_object &sto, bool &complete) { + complete = false; std::string new_tx = ""; - //new_tx = sign_transaction_raw(tx, complete); - new_tx = sign_transaction_psbt(tx_str, complete); - //new_tx = sign_transaction_standalone(tx, complete); + //new_tx = sign_transaction_raw(sto, complete); + new_tx = sign_transaction_psbt(sto, complete); + //new_tx = sign_transaction_standalone(sto, complete); return new_tx; } -bool sidechain_net_handler_bitcoin::send_transaction(const std::string &tx_str) { - return bitcoin_client->sendrawtransaction(tx_str); +bool sidechain_net_handler_bitcoin::send_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { + sidechain_transaction = ""; + //return send_transaction_raw(sto, sidechain_transaction); + return send_transaction_psbt(sto, sidechain_transaction); } std::string sidechain_net_handler_bitcoin::create_transaction_raw(const std::vector &inputs, const fc::flat_map outputs) { @@ -1209,8 +1231,10 @@ std::string sidechain_net_handler_bitcoin::create_transaction_standalone(const s return ""; } -std::string sidechain_net_handler_bitcoin::sign_transaction_raw(const std::string &tx_str, bool &complete) { - if (tx_str.empty()) { +std::string sidechain_net_handler_bitcoin::sign_transaction_raw(const sidechain_transaction_object &sto, bool &complete) { + complete = false; + + if (sto.transaction.empty()) { elog("Signing failed, tx string is empty"); return ""; } @@ -1219,7 +1243,7 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_raw(const std::strin bitcoin_client->walletpassphrase(wallet_password, 5); } - std::string reply_str = bitcoin_client->signrawtransactionwithwallet(tx_str); + std::string reply_str = bitcoin_client->signrawtransactionwithwallet(sto.transaction); std::stringstream ss(reply_str); boost::property_tree::ptree json; @@ -1227,7 +1251,7 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_raw(const std::strin boost::property_tree::ptree json_res = json.get_child("result"); if ((json_res.count("hex") == 0) || (json_res.count("complete") == 0)) { - elog("Failed to process raw transaction ${tx}", ("tx", tx_str)); + elog("Failed to process raw transaction ${tx}", ("tx", sto.transaction)); return ""; } @@ -1241,8 +1265,10 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_raw(const std::strin return new_tx_raw; } -std::string sidechain_net_handler_bitcoin::sign_transaction_psbt(const std::string &tx_str, bool &complete) { - if (tx_str.empty()) { +std::string sidechain_net_handler_bitcoin::sign_transaction_psbt(const sidechain_transaction_object &sto, bool &complete) { + complete = false; + + if (sto.transaction.empty()) { elog("Signing failed, tx string is empty"); return ""; } @@ -1251,7 +1277,7 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_psbt(const std::stri bitcoin_client->walletpassphrase(wallet_password, 5); } - std::string reply_str = bitcoin_client->walletprocesspsbt(tx_str); + std::string reply_str = bitcoin_client->walletprocesspsbt(sto.transaction); std::stringstream ss(reply_str); boost::property_tree::ptree json; @@ -1259,42 +1285,105 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_psbt(const std::stri boost::property_tree::ptree json_res = json.get_child("result"); if ((json_res.count("psbt") == 0) || (json_res.count("complete") == 0)) { - elog("Failed to process psbt transaction ${tx}", ("tx", tx_str)); + elog("Failed to process psbt transaction ${tx}", ("tx", sto.transaction)); return ""; } std::string new_tx_psbt = json_res.get("psbt"); bool complete_psbt = json_res.get("complete"); - if (complete_psbt) { - std::string reply_str = bitcoin_client->finalizepsbt(new_tx_psbt); + if (!complete_psbt) { + // Try to combine and finalize + vector psbts; + for (auto signature : sto.signatures) { + if (!signature.second.empty()) { + psbts.push_back(signature.second); + } + } + psbts.push_back(new_tx_psbt); + + std::string reply_str = bitcoin_client->combinepsbt(psbts); std::stringstream ss(reply_str); boost::property_tree::ptree json; boost::property_tree::read_json(ss, json); - boost::property_tree::ptree json_res = json.get_child("result"); + if (json.count("error") && json.get_child("error").empty()) { - if ((json_res.count("hex") == 0) || (json_res.count("complete") == 0)) { - elog("Failed to finalize psbt transaction ${tx}", ("tx", tx_str)); - return ""; - } + std::string new_tx_psbt = json.get("result"); - std::string new_tx_raw = json_res.get("hex"); - bool complete_raw = json_res.get("complete"); + std::string reply_str_fin = bitcoin_client->finalizepsbt(new_tx_psbt); + std::stringstream ss_fin(reply_str_fin); + boost::property_tree::ptree json_fin; + boost::property_tree::read_json(ss_fin, json_fin); + boost::property_tree::ptree json_res = json_fin.get_child("result"); - if (complete_raw) { - complete = true; - return new_tx_raw; + if (json_res.count("hex") && json_res.count("complete")) { + complete_psbt = json_res.get("complete"); + } } } + + complete = complete_psbt; return new_tx_psbt; } -std::string sidechain_net_handler_bitcoin::sign_transaction_standalone(const std::string &tx_str, bool &complete) { +std::string sidechain_net_handler_bitcoin::sign_transaction_standalone(const sidechain_transaction_object &sto, bool &complete) { + complete = false; + complete = true; return ""; } +bool sidechain_net_handler_bitcoin::send_transaction_raw(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { + sidechain_transaction = ""; + + return bitcoin_client->sendrawtransaction(sto.transaction); +} + +bool sidechain_net_handler_bitcoin::send_transaction_psbt(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { + sidechain_transaction = ""; + + vector psbts; + for (auto signature : sto.signatures) { + if (!signature.second.empty()) { + psbts.push_back(signature.second); + } + } + + std::string reply_str = bitcoin_client->combinepsbt(psbts); + + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (json.count("error") && !json.get_child("error").empty()) { + elog("Failed to combine psbt transactions from ${sto}", ("sto", sto)); + return false; + } + + std::string new_tx_psbt = json.get("result"); + + std::string reply_str_fin = bitcoin_client->finalizepsbt(new_tx_psbt); + std::stringstream ss_fin(reply_str_fin); + boost::property_tree::ptree json_fin; + boost::property_tree::read_json(ss_fin, json_fin); + boost::property_tree::ptree json_res = json_fin.get_child("result"); + + if ((json_res.count("hex") == 0) || (json_res.count("complete") == 0)) { + elog("Failed to finalize psbt transaction ${tx}", ("tx", new_tx_psbt)); + return false; + } + + std::string new_tx_raw = json_res.get("hex"); + bool complete_raw = json_res.get("complete"); + + if (complete_raw) { + return bitcoin_client->sendrawtransaction(new_tx_raw); + } + + return false; +} // namespace peerplays_sidechain + void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) { std::string block = bitcoin_client->getblock(event_data); if (block != "") { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 8dd39b22..3f6b777d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -46,7 +46,8 @@ std::string sidechain_net_handler_peerplays::process_sidechain_transaction(const return sto.transaction; } -bool sidechain_net_handler_peerplays::send_sidechain_transaction(const sidechain_transaction_object &sto) { +bool sidechain_net_handler_peerplays::send_sidechain_transaction(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { + sidechain_transaction = ""; return true; }