From 4a7503d9a8aa5ad37d815ce682ff3ddb83edb2f5 Mon Sep 17 00:00:00 2001 From: gladcow Date: Sat, 28 Mar 2020 00:52:23 +0300 Subject: [PATCH] change signing logic according to last changes --- .../peerplays_sidechain/bitcoin_utils.cpp | 40 ++++++++++++-- .../peerplays_sidechain/bitcoin_utils.hpp | 7 ++- .../sidechain_net_handler_bitcoin.cpp | 53 +++++++++++-------- programs/witness_node/genesis.json | 2 +- .../bitcoin_utils_test.cpp | 12 ++++- 5 files changed, 85 insertions(+), 29 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/bitcoin_utils.cpp b/libraries/plugins/peerplays_sidechain/bitcoin_utils.cpp index e9b4f6ad..72319042 100644 --- a/libraries/plugins/peerplays_sidechain/bitcoin_utils.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin_utils.cpp @@ -786,7 +786,7 @@ bytes get_weighted_multisig_redeem_script(std::vector &in_amounts) +void read_tx_data_from_string(const std::string &string_buf, bytes &tx, std::vector &in_amounts, bytes &redeem_script) { std::stringstream ss(string_buf); boost::property_tree::ptree json; @@ -798,9 +798,13 @@ void read_tx_data_from_string(const std::string &string_buf, bytes &tx, std::vec in_amounts.clear(); for(auto &v: json.get_child("in_amounts")) in_amounts.push_back(fc::to_uint64(v.second.data())); + std::string script = json.get("redeem_script"); + redeem_script.clear(); + redeem_script.resize(script.size() / 2); + fc::from_hex(script, (char*)&redeem_script[0], redeem_script.size()); } -std::string save_tx_data_to_string(const bytes &tx, const std::vector &in_amounts) +std::string save_tx_data_to_string(const bytes &tx, const std::vector &in_amounts, const bytes &redeem_script) { std::string res = "{\"tx_hex\":\"" + fc::to_hex((const char*)&tx[0], tx.size()) + "\",\"in_amounts\":["; for (unsigned int idx = 0; idx < in_amounts.size(); ++idx) { @@ -808,7 +812,37 @@ std::string save_tx_data_to_string(const bytes &tx, const std::vector if (idx != in_amounts.size() - 1) res += ","; } - res += "]}"; + res += "],\"redeem_script\":\"" + fc::to_hex((const char*)&redeem_script[0], redeem_script.size()) + "\"}"; + return res; +} + +std::vector read_bytes_array_from_string(const std::string &string_buf) +{ + std::stringstream ss(string_buf); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + std::vector data; + for(auto &v: json) + { + std::string hex = v.second.data(); + bytes item; + item.resize(hex.size() / 2); + fc::from_hex(hex, (char*)&item[0], item.size()); + data.push_back(item); + } + return data; +} + +std::string write_bytes_array_to_string(const std::vector& data) +{ + std::string res = "["; + for (unsigned int idx = 0; idx < data.size(); ++idx) { + res += "\"" + fc::to_hex((char*)&data[idx][0], data[idx].size()) + "\""; + if (idx != data.size() - 1) + res += ","; + } + res += "]"; return res; } diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin_utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin_utils.hpp index 5f7c4f3b..62532c82 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin_utils.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin_utils.hpp @@ -68,8 +68,11 @@ bytes add_signatures_to_unsigned_tx(const bytes &unsigned_tx, const std::vector> &signatures, const bytes &redeem_script); -void read_tx_data_from_string(const std::string &string_buf, bytes& tx, std::vector& in_amounts); -std::string save_tx_data_to_string(const bytes& tx, const std::vector& in_amounts); +void read_tx_data_from_string(const std::string &string_buf, bytes& tx, std::vector& in_amounts, bytes& redeem_script); +std::string save_tx_data_to_string(const bytes& tx, const std::vector& in_amounts, const bytes& redeem_script); + +std::vector read_bytes_array_from_string(const std::string &string_buf); +std::string write_bytes_array_to_string(const std::vector& data); struct btc_outpoint { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index d4cb50b2..cb03c186 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -897,7 +897,7 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() { vector son_votes; for (const son_info &si : active_sons) { son_pubkeys_bitcoin.push_back(si.sidechain_public_keys.at(sidechain_type::bitcoin)); - son_votes.push_back(si.total_votes); + son_votes.push_back(si.weight); } std::string full_address_info = create_multisig_address(son_pubkeys_bitcoin, son_votes); @@ -1317,13 +1317,10 @@ std::string sidechain_net_handler_bitcoin::create_transaction_standalone(const s tx.vout.push_back(btc_out(out.first, out.second * 100000000.0)); bytes buf; tx.to_bytes(buf); - if (redeem_script.size()) { - bytes redeem_script_bin; - redeem_script_bin.resize(redeem_script.size() / 2); - fc::from_hex(redeem_script, (char*)&redeem_script_bin[0], redeem_script_bin.size()); - buf = add_dummy_signatures_for_pw_transfer(buf, redeem_script_bin, 15); // TODO: get son number from the script - } - return save_tx_data_to_string(buf, in_amounts); + bytes redeem_script_bin; + redeem_script_bin.resize(redeem_script.size() / 2); + fc::from_hex(redeem_script, (char*)&redeem_script_bin[0], redeem_script_bin.size()); + return save_tx_data_to_string(buf, in_amounts, redeem_script_bin); } std::string sidechain_net_handler_bitcoin::sign_transaction_raw(const sidechain_transaction_object &sto, bool &complete) { @@ -1435,27 +1432,25 @@ std::string sidechain_net_handler_bitcoin::sign_transaction_standalone(const sid already_signed += son.total_votes; } set owned_sons = plugin.get_sons(); - bytes partially_signed_tx; + bytes unsigned_tx; vector in_amounts; - read_tx_data_from_string(sto.transaction, partially_signed_tx, in_amounts); + bytes redeem_script; + read_tx_data_from_string(sto.transaction, unsigned_tx, in_amounts, redeem_script); + son_object active_son = plugin.get_current_son_object(); + vector signatures; for (unsigned idx = 0; idx < sto.signatures.size(); ++idx) { if(!sto.signatures[idx].second.empty()) continue; - if(!owned_sons.count(sto.signatures[idx].first)) + if(sto.signatures[idx].first != active_son.id) continue; - son_object son = plugin.get_son_object(sto.signatures[idx].first); - std::string btc_public_key = son.sidechain_public_keys[sidechain_type::bitcoin]; + std::string btc_public_key = active_son.sidechain_public_keys[sidechain_type::bitcoin]; fc::optional btc_private_key = graphene::utilities::wif_to_key(private_keys[btc_public_key]); - ilog("Sign with public key ${pub}, private key ${priv}, index ${idx}", - ("pub", btc_public_key)("priv", *btc_private_key)("idx", idx)); - partially_signed_tx = partially_sign_pw_transfer_transaction(partially_signed_tx, in_amounts, *btc_private_key, idx); - already_signed += son.total_votes; + already_signed += active_son.total_votes; + signatures = signatures_for_raw_transaction(unsigned_tx, in_amounts, redeem_script, *btc_private_key); } complete = (3 * already_signed > 2 * total_votes); - if(complete) - return fc::to_hex((const char*)&partially_signed_tx[0], partially_signed_tx.size()); - return save_tx_data_to_string(partially_signed_tx, in_amounts); + return write_bytes_array_to_string(signatures); } bool sidechain_net_handler_bitcoin::send_transaction_raw(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { @@ -1511,7 +1506,23 @@ bool sidechain_net_handler_bitcoin::send_transaction_psbt(const sidechain_transa bool sidechain_net_handler_bitcoin::send_transaction_standalone(const sidechain_transaction_object &sto, std::string &sidechain_transaction) { sidechain_transaction = ""; - return bitcoin_client->sendrawtransaction(sto.transaction); + bytes unsigned_tx; + vector in_amounts; + bytes redeem_script; + read_tx_data_from_string(sto.transaction, unsigned_tx, in_amounts, redeem_script); + uint32_t inputs_number = in_amounts.size(); + vector dummy; + dummy.resize(inputs_number); + vector> signatures; + for (unsigned idx = 0; idx < sto.signatures.size(); ++idx) { + if(sto.signatures[idx].second.empty()) + signatures.push_back(dummy); + else + signatures.push_back(read_bytes_array_from_string(sto.signatures[idx].second)); + } + bytes signed_tx = add_signatures_to_unsigned_tx(unsigned_tx, signatures, redeem_script); + + return bitcoin_client->sendrawtransaction(fc::to_hex((char*)&signed_tx[0], signed_tx.size())); } void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) { diff --git a/programs/witness_node/genesis.json b/programs/witness_node/genesis.json index 12f2581e..54a58c71 100644 --- a/programs/witness_node/genesis.json +++ b/programs/witness_node/genesis.json @@ -333,7 +333,7 @@ "scale": 10000 }, "block_interval": 3, - "maintenance_interval": 86400, + "maintenance_interval": 120, "maintenance_skip_slots": 3, "committee_proposal_review_period": 1209600, "maximum_transaction_size": 2048, diff --git a/tests/peerplays_sidechain/bitcoin_utils_test.cpp b/tests/peerplays_sidechain/bitcoin_utils_test.cpp index b764de76..2265acac 100644 --- a/tests/peerplays_sidechain/bitcoin_utils_test.cpp +++ b/tests/peerplays_sidechain/bitcoin_utils_test.cpp @@ -33,12 +33,20 @@ BOOST_AUTO_TEST_CASE(tx_data_serialization) { bytes source_tx({0, 1, 2, 3, 4, 5}); std::vector source_ins({6, 7, 8, 9, 10}); - std::string buf = save_tx_data_to_string(source_tx, source_ins); + bytes source_script({11, 12, 13, 14}); + std::string buf = save_tx_data_to_string(source_tx, source_ins, source_script); bytes destination_tx; std::vector destination_ins; - read_tx_data_from_string(buf, destination_tx, destination_ins); + bytes destination_script; + read_tx_data_from_string(buf, destination_tx, destination_ins, destination_script); BOOST_REQUIRE(source_tx == destination_tx); BOOST_REQUIRE(source_ins == destination_ins); + BOOST_REQUIRE(source_script == destination_script); + + std::vector source_array({source_tx, source_script, source_script}); + buf = write_bytes_array_to_string(source_array); + std::vector destination_array = read_bytes_array_from_string(buf); + BOOST_REQUIRE(source_array == destination_array); } BOOST_AUTO_TEST_CASE(pw_transfer)