Compare commits
6 commits
master
...
hotfix-raw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a46d9a3dc | ||
|
|
ca36856044 | ||
|
|
019da1261a | ||
|
|
69bbf2c082 | ||
|
|
d3ce89a90f | ||
|
|
2a2440acf9 |
5 changed files with 95 additions and 102 deletions
|
|
@ -96,49 +96,4 @@ std::string write_transaction_data(const std::string &tx, const std::vector<uint
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<prev_out> get_outputs_from_transaction_by_address(const std::string &tx_json, const std::string &to_address) {
|
|
||||||
std::stringstream ss(tx_json);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json(ss, json);
|
|
||||||
std::vector<prev_out> result;
|
|
||||||
|
|
||||||
if (json.count("error") && !json.get_child("error").empty()) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tx_txid = json.get<std::string>("result.txid");
|
|
||||||
|
|
||||||
for (auto &vout : json.get_child("result.vout")) {
|
|
||||||
std::vector<std::string> to_addresses;
|
|
||||||
if (vout.second.find("scriptPubKey") == vout.second.not_found() ||
|
|
||||||
vout.second.get_child("scriptPubKey").find("addresses") == vout.second.get_child("scriptPubKey").not_found()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &address : vout.second.get_child("scriptPubKey.addresses")) {
|
|
||||||
to_addresses.push_back(address.second.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((to_address == "") ||
|
|
||||||
(std::find(to_addresses.begin(), to_addresses.end(), to_address) != to_addresses.end())) {
|
|
||||||
std::string tx_amount_s = vout.second.get<std::string>("value");
|
|
||||||
tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end());
|
|
||||||
uint64_t tx_amount = std::stoll(tx_amount_s);
|
|
||||||
|
|
||||||
std::string tx_vout_s = vout.second.get<std::string>("n");
|
|
||||||
uint64_t tx_vout = std::stoll(tx_vout_s);
|
|
||||||
|
|
||||||
prev_out pout;
|
|
||||||
pout.hash_tx = tx_txid;
|
|
||||||
pout.n_vout = tx_vout;
|
|
||||||
pout.amount = tx_amount;
|
|
||||||
result.push_back(pout);
|
|
||||||
if (to_address == "") {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}} // namespace graphene::peerplays_sidechain::bitcoin
|
}}} // namespace graphene::peerplays_sidechain::bitcoin
|
||||||
|
|
|
||||||
|
|
@ -42,15 +42,6 @@ struct prev_out {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const prev_out &obj) const {
|
|
||||||
if (this->hash_tx == obj.hash_tx &&
|
|
||||||
this->n_vout == obj.n_vout &&
|
|
||||||
this->amount == obj.amount) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string hash_tx;
|
std::string hash_tx;
|
||||||
uint32_t n_vout;
|
uint32_t n_vout;
|
||||||
uint64_t amount;
|
uint64_t amount;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,4 @@ void read_transaction_data(const std::string &string_buf, std::string &tx_hex, s
|
||||||
|
|
||||||
std::string write_transaction_data(const std::string &tx, const std::vector<uint64_t> &in_amounts, const std::string &redeem_script);
|
std::string write_transaction_data(const std::string &tx, const std::vector<uint64_t> &in_amounts, const std::string &redeem_script);
|
||||||
|
|
||||||
std::vector<prev_out> get_outputs_from_transaction_by_address(const std::string &tx_json, const std::string &to_address = "");
|
|
||||||
|
|
||||||
}}} // namespace graphene::peerplays_sidechain::bitcoin
|
}}} // namespace graphene::peerplays_sidechain::bitcoin
|
||||||
|
|
@ -34,6 +34,7 @@ public:
|
||||||
std::string finalizepsbt(std::string const &tx_psbt);
|
std::string finalizepsbt(std::string const &tx_psbt);
|
||||||
std::string getaddressinfo(const std::string &address);
|
std::string getaddressinfo(const std::string &address);
|
||||||
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
|
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
|
||||||
|
std::string getrawtransaction(const std::string &txid, const bool verbose = false);
|
||||||
std::string gettransaction(const std::string &txid, const bool include_watch_only = false);
|
std::string gettransaction(const std::string &txid, const bool include_watch_only = false);
|
||||||
void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false);
|
void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false);
|
||||||
std::vector<btc_txout> listunspent(const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
std::vector<btc_txout> listunspent(const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
||||||
|
|
@ -85,7 +86,6 @@ public:
|
||||||
sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options);
|
sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options);
|
||||||
virtual ~sidechain_net_handler_bitcoin();
|
virtual ~sidechain_net_handler_bitcoin();
|
||||||
|
|
||||||
std::string get_current_primary_wallet_address();
|
|
||||||
bool process_proposal(const proposal_object &po);
|
bool process_proposal(const proposal_object &po);
|
||||||
void process_primary_wallet();
|
void process_primary_wallet();
|
||||||
void process_sidechain_addresses();
|
void process_sidechain_addresses();
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,8 @@ std::string bitcoin_rpc_client::decoderawtransaction(std::string const &tx_hex)
|
||||||
boost::property_tree::read_json(ss, json);
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
if (reply.status == 200) {
|
if (reply.status == 200) {
|
||||||
|
std::stringstream ss;
|
||||||
|
boost::property_tree::json_parser::write_json(ss, json.get_child("result"));
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -458,6 +460,34 @@ std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) {
|
||||||
|
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getrawtransaction\", \"method\": "
|
||||||
|
"\"getrawtransaction\", \"params\": [");
|
||||||
|
|
||||||
|
std::string params = "\"" + txid + "\", " + (verbose ? "true" : "false");
|
||||||
|
body = body + params + "] }";
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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::gettransaction(const std::string &txid, const bool include_watch_only) {
|
std::string bitcoin_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) {
|
||||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"gettransaction\", \"method\": "
|
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"gettransaction\", \"method\": "
|
||||||
"\"gettransaction\", \"params\": [");
|
"\"gettransaction\", \"params\": [");
|
||||||
|
|
@ -915,22 +945,6 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::get_current_primary_wallet_address() {
|
|
||||||
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
|
||||||
auto obj = idx.rbegin();
|
|
||||||
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
|
|
||||||
std::stringstream ss(pw_address_json);
|
|
||||||
boost::property_tree::ptree json;
|
|
||||||
boost::property_tree::read_json(ss, json);
|
|
||||||
|
|
||||||
std::string pw_address = json.get<std::string>("address");
|
|
||||||
return pw_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) {
|
bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) {
|
||||||
|
|
||||||
ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id()));
|
ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id()));
|
||||||
|
|
@ -1041,24 +1055,40 @@ 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->gettransaction(swdo_txid, true);
|
std::string tx_str = bitcoin_client->getrawtransaction(swdo_txid, true);
|
||||||
std::stringstream tx_ss(tx_str);
|
std::stringstream tx_ss(tx_str);
|
||||||
boost::property_tree::ptree tx_json;
|
boost::property_tree::ptree tx_json;
|
||||||
boost::property_tree::read_json(tx_ss, 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_hex = tx_json.get<std::string>("result.hex");
|
std::string tx_address = "";
|
||||||
std::string tx_hex_json = bitcoin_client->decoderawtransaction(tx_hex);
|
int64_t tx_amount = -1;
|
||||||
std::vector<bitcoin::prev_out> pouts = bitcoin::get_outputs_from_transaction_by_address(tx_hex_json, swdo_address);
|
int64_t tx_vout = -1;
|
||||||
|
|
||||||
bitcoin::prev_out pout;
|
for (auto &input : tx_json.get_child("result.vout")) {
|
||||||
pout.hash_tx = swdo_txid;
|
std::string tx_vout_s = input.second.get<std::string>("n");
|
||||||
pout.n_vout = swdo_vout;
|
tx_vout = std::stoll(tx_vout_s);
|
||||||
pout.amount = swdo_amount;
|
if (tx_vout == swdo_vout) {
|
||||||
|
for (auto &address : input.second.get_child("scriptPubKey.addresses")) {
|
||||||
|
if (address.second.data() == swdo_address) {
|
||||||
|
tx_address = address.second.data();
|
||||||
|
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 = (std::find(pouts.begin(), pouts.end(), pout) != pouts.end()) &&
|
process_ok = (swdo_txid == tx_txid) &&
|
||||||
|
(swdo_address == tx_address) &&
|
||||||
|
(swdo_amount == tx_amount) &&
|
||||||
|
(swdo_vout == tx_vout) &&
|
||||||
(gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations);
|
(gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1079,14 +1109,6 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object_id.is<son_wallet_withdraw_id_type>()) {
|
|
||||||
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
|
|
||||||
const auto swwo = idx.find(object_id);
|
|
||||||
if (swwo != idx.end()) {
|
|
||||||
tx_str = create_withdrawal_transaction(*swwo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction_ok = (op_tx_str == tx_str);
|
transaction_ok = (op_tx_str == tx_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1317,7 +1339,7 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() {
|
||||||
|
|
||||||
bool sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_object &swdo) {
|
bool sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||||
|
|
||||||
if (proposal_exists(chain::operation::tag<chain::sidechain_transaction_create_operation>::value, swdo.id)) {
|
if (proposal_exists(chain::operation::tag<chain::son_wallet_deposit_process_operation>::value, swdo.id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1361,7 +1383,7 @@ bool sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_obj
|
||||||
|
|
||||||
bool sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
bool sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||||
|
|
||||||
if (proposal_exists(chain::operation::tag<chain::sidechain_transaction_create_operation>::value, swwo.id)) {
|
if (proposal_exists(chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value, swwo.id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1423,7 +1445,7 @@ int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidech
|
||||||
return settle_amount;
|
return settle_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tx_str = bitcoin_client->gettransaction(sto.sidechain_transaction, true);
|
std::string tx_str = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true);
|
||||||
std::stringstream tx_ss(tx_str);
|
std::stringstream tx_ss(tx_str);
|
||||||
boost::property_tree::ptree tx_json;
|
boost::property_tree::ptree tx_json;
|
||||||
boost::property_tree::read_json(tx_ss, tx_json);
|
boost::property_tree::read_json(tx_ss, tx_json);
|
||||||
|
|
@ -1432,19 +1454,35 @@ int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidech
|
||||||
return settle_amount;
|
return settle_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chain::global_property_object &gpo = database.get_global_properties();
|
||||||
|
|
||||||
|
using namespace bitcoin;
|
||||||
|
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
|
||||||
|
for (auto si : sto.signers) {
|
||||||
|
std::string pub_key_str = si.sidechain_public_keys.at(sidechain_type::bitcoin);
|
||||||
|
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
|
||||||
|
pubkey_weights.push_back(std::make_pair(pub_key, si.weight));
|
||||||
|
}
|
||||||
|
btc_weighted_multisig_address addr(pubkey_weights);
|
||||||
|
|
||||||
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();
|
||||||
const chain::global_property_object &gpo = database.get_global_properties();
|
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>()) {
|
||||||
std::string tx_hex = tx_json.get<std::string>("result.hex");
|
for (auto &input : tx_json.get_child("result.vout")) {
|
||||||
std::string tx_hex_json = bitcoin_client->decoderawtransaction(tx_hex);
|
for (auto &address : input.second.get_child("scriptPubKey.addresses")) {
|
||||||
std::vector<bitcoin::prev_out> pouts = bitcoin::get_outputs_from_transaction_by_address(tx_hex_json);
|
if (address.second.data() == tx_address) {
|
||||||
if (pouts.size() > 0) {
|
std::string tx_amount_s = input.second.get<std::string>("value");
|
||||||
settle_amount = pouts[0].amount;
|
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 = tx_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
||||||
|
|
@ -1517,9 +1555,20 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_wallet_deposit_object &swdo) {
|
std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_wallet_deposit_object &swdo) {
|
||||||
|
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||||
|
auto obj = idx.rbegin();
|
||||||
|
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
//Get redeem script for deposit address
|
//Get redeem script for deposit address
|
||||||
std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_to);
|
std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_to);
|
||||||
std::string pw_address = get_current_primary_wallet_address();
|
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
|
||||||
|
|
||||||
|
std::stringstream ss(pw_address_json);
|
||||||
|
boost::property_tree::ptree json;
|
||||||
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
|
std::string pw_address = json.get<std::string>("address");
|
||||||
|
|
||||||
std::string txid = swdo.sidechain_transaction_id;
|
std::string txid = swdo.sidechain_transaction_id;
|
||||||
std::string suid = swdo.sidechain_uid;
|
std::string suid = swdo.sidechain_uid;
|
||||||
|
|
@ -1667,7 +1716,7 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
|
||||||
signatures.push_back(read_byte_arrays_from_string(sto.signatures[idx].second));
|
signatures.push_back(read_byte_arrays_from_string(sto.signatures[idx].second));
|
||||||
}
|
}
|
||||||
//Add empty sig for user signature for Deposit transaction
|
//Add empty sig for user signature for Deposit transaction
|
||||||
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
|
if (sto.object_id.type() == son_wallet_deposit_object::type_id) {
|
||||||
add_signatures_to_transaction_user_weighted_multisig(tx, signatures);
|
add_signatures_to_transaction_user_weighted_multisig(tx, signatures);
|
||||||
} else {
|
} else {
|
||||||
add_signatures_to_transaction_weighted_multisig(tx, signatures);
|
add_signatures_to_transaction_weighted_multisig(tx, signatures);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue