Compare commits

...

1 commit

Author SHA1 Message Date
Srdjan Obucina
d6c6dfff16 Parallelizing sidechain transaction signing 2020-03-25 19:34:31 +01:00
10 changed files with 214 additions and 99 deletions

View file

@ -2,6 +2,7 @@
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/types.hpp>
#include <graphene/chain/sidechain_defs.hpp>
#include <graphene/chain/son_info.hpp>
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<son_id_type> signers;
std::vector<son_info> 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) )
(sidechain_transaction_id)
(sidechain_transaction) )

View file

@ -20,9 +20,13 @@ namespace graphene { namespace chain {
sidechain_type sidechain;
object_id_type object_id;
std::string transaction;
std::vector<std::pair<son_id_type, bool>> signers;
std::vector<son_info> signers;
std::vector<std::pair<son_id_type, std::string>> 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) )

View file

@ -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;
});

View file

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

View file

@ -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<std::string> public_keys);
std::string combinepsbt(const vector<std::string> &psbts);
std::string createpsbt(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs);
std::string createrawtransaction(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> 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<void> on_changed_objects_task;
std::string create_transaction(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> 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<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs);
std::string create_transaction_psbt(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs);
std::string create_transaction_standalone(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> 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<info_for_vin> extract_info_from_block(const std::string &_block);

View file

@ -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);

View file

@ -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();
}
}
}

View file

@ -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");
}

View file

@ -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<std::string> &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<btc_txout> &ins, const fc::flat_map<std::string, double> 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<btc_txout> &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::vector<btc_txout
}
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__));
@ -273,7 +307,7 @@ uint64_t bitcoin_rpc_client::estimatesmartfee() {
"\"method\": \"estimatesmartfee\", \"params\": [") +
std::to_string(confirmation_target_blocks) + 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__));
@ -310,7 +344,7 @@ std::string bitcoin_rpc_client::finalizepsbt(std::string const &tx_psbt) {
"\"finalizepsbt\", \"params\": [\"" +
tx_psbt + "\"] }");
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__));
@ -392,7 +426,7 @@ void bitcoin_rpc_client::importaddress(const std::string &address_or_script) {
"\"method\": \"importaddress\", \"params\": [") +
std::string("\"") + address_or_script + std::string("\"") + 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__));
@ -513,7 +547,7 @@ bool bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) {
"\"method\": \"sendrawtransaction\", \"params\": [") +
std::string("\"") + tx_hex + std::string("\"") + 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__));
@ -541,7 +575,7 @@ std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string &
std::string params = "\"" + tx_hash + "\"";
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__));
@ -622,7 +656,7 @@ std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) {
"\"walletprocesspsbt\", \"params\": [\"" +
tx_psbt + "\"] }");
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__));
@ -901,18 +935,12 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() {
if (!tx_str.empty()) {
auto signer_sons = prev_sw->sons;
std::vector<son_id_type> 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<son_id_type> 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<son_id_type> 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<btc_txout> &inputs, const fc::flat_map<std::string, double> 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<std::string>("psbt");
bool complete_psbt = json_res.get<bool>("complete");
if (complete_psbt) {
std::string reply_str = bitcoin_client->finalizepsbt(new_tx_psbt);
if (!complete_psbt) {
// Try to combine and finalize
vector<std::string> 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<std::string>("result");
std::string new_tx_raw = json_res.get<std::string>("hex");
bool complete_raw = json_res.get<bool>("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<bool>("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<std::string> 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<std::string>("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<std::string>("hex");
bool complete_raw = json_res.get<bool>("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 != "") {

View file

@ -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;
}