change signing logic according to last changes

This commit is contained in:
gladcow 2020-03-28 00:52:23 +03:00
parent 3035e5294f
commit 4a7503d9a8
5 changed files with 85 additions and 29 deletions

View file

@ -786,7 +786,7 @@ bytes get_weighted_multisig_redeem_script(std::vector<std::pair<std::string, uin
return generate_redeem_script(key_data);
}
void read_tx_data_from_string(const std::string &string_buf, bytes &tx, std::vector<uint64_t> &in_amounts)
void read_tx_data_from_string(const std::string &string_buf, bytes &tx, std::vector<uint64_t> &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<std::string>("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<uint64_t> &in_amounts)
std::string save_tx_data_to_string(const bytes &tx, const std::vector<uint64_t> &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<uint64_t>
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<bytes> 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<bytes> 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<bytes>& 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;
}

View file

@ -68,8 +68,11 @@ bytes add_signatures_to_unsigned_tx(const bytes &unsigned_tx,
const std::vector<std::vector<bytes>> &signatures,
const bytes &redeem_script);
void read_tx_data_from_string(const std::string &string_buf, bytes& tx, std::vector<uint64_t>& in_amounts);
std::string save_tx_data_to_string(const bytes& tx, const std::vector<uint64_t>& in_amounts);
void read_tx_data_from_string(const std::string &string_buf, bytes& tx, std::vector<uint64_t>& in_amounts, bytes& redeem_script);
std::string save_tx_data_to_string(const bytes& tx, const std::vector<uint64_t>& in_amounts, const bytes& redeem_script);
std::vector<bytes> read_bytes_array_from_string(const std::string &string_buf);
std::string write_bytes_array_to_string(const std::vector<bytes>& data);
struct btc_outpoint {

View file

@ -897,7 +897,7 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() {
vector<uint64_t> 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<son_id_type> owned_sons = plugin.get_sons();
bytes partially_signed_tx;
bytes unsigned_tx;
vector<uint64_t> 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<bytes> 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<fc::ecc::private_key> 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<uint64_t> 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<bytes> dummy;
dummy.resize(inputs_number);
vector<vector<bytes>> 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) {

View file

@ -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,

View file

@ -33,12 +33,20 @@ BOOST_AUTO_TEST_CASE(tx_data_serialization)
{
bytes source_tx({0, 1, 2, 3, 4, 5});
std::vector<uint64_t> 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<uint64_t> 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<bytes> source_array({source_tx, source_script, source_script});
buf = write_bytes_array_to_string(source_array);
std::vector<bytes> destination_array = read_bytes_array_from_string(buf);
BOOST_REQUIRE(source_array == destination_array);
}
BOOST_AUTO_TEST_CASE(pw_transfer)