Fix memory leak in libbitcoin
This commit is contained in:
parent
fef5131a96
commit
4d161ceeb2
4 changed files with 195 additions and 178 deletions
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain {
|
namespace graphene { namespace peerplays_sidechain {
|
||||||
|
|
||||||
libbitcoin_client::libbitcoin_client(std::string url) :
|
libbitcoin_client::libbitcoin_client(const std::string &url) :
|
||||||
obelisk_client(LIBBITCOIN_SERVER_TIMEOUT, LIBBITCOIN_SERVER_RETRIES) {
|
obelisk_client(LIBBITCOIN_SERVER_TIMEOUT, LIBBITCOIN_SERVER_RETRIES) {
|
||||||
|
|
||||||
std::string reg_expr = "^((?P<Protocol>https|http|tcp):\\/\\/)?(?P<Host>[a-zA-Z0-9\\-\\.]+)(:(?P<Port>\\d{1,5}))?(?P<Target>\\/.+)?";
|
const std::string reg_expr = "^((?P<Protocol>https|http|tcp):\\/\\/)?(?P<Host>[a-zA-Z0-9\\-\\.]+)(:(?P<Port>\\d{1,5}))?(?P<Target>\\/.+)?";
|
||||||
boost::xpressive::sregex sr = boost::xpressive::sregex::compile(reg_expr);
|
boost::xpressive::sregex sr = boost::xpressive::sregex::compile(reg_expr);
|
||||||
|
|
||||||
boost::xpressive::smatch sm;
|
boost::xpressive::smatch sm;
|
||||||
|
|
@ -38,10 +38,10 @@ libbitcoin_client::libbitcoin_client(std::string url) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t port_num = std::stoi(port);
|
const auto port_num = static_cast<uint16_t>(std::stoi(port));
|
||||||
std::string final_url = protocol + "://" + host;
|
const std::string final_url = protocol + "://" + host;
|
||||||
|
|
||||||
libbitcoin::config::endpoint address(final_url, port_num);
|
const libbitcoin::config::endpoint address(final_url, port_num);
|
||||||
|
|
||||||
libbitcoin::client::connection_type connection;
|
libbitcoin::client::connection_type connection;
|
||||||
connection.retries = LIBBITCOIN_SERVER_RETRIES;
|
connection.retries = LIBBITCOIN_SERVER_RETRIES;
|
||||||
|
|
@ -54,22 +54,20 @@ libbitcoin_client::libbitcoin_client(std::string url) :
|
||||||
is_connected = true;
|
is_connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string libbitcoin_client::send_transaction(std::string tx) {
|
std::string libbitcoin_client::send_transaction(const std::string &tx) {
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
auto error_handler = [&](const std::error_code &ec) {
|
auto error_handler = [](const std::error_code &ec) {
|
||||||
elog("error on sending bitcoin transaction ${error_code}", ("error_code", ec.message()));
|
elog("error on sending bitcoin transaction ${error_code}", ("error_code", ec.message()));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto result_handler = [&](libbitcoin::code result_code) {
|
auto result_handler = [&res](libbitcoin::code result_code) {
|
||||||
ilog("result code on sending transaction ${result_code}", ("result_code", result_code.message()));
|
ilog("result code on sending transaction ${result_code}", ("result_code", result_code.message()));
|
||||||
res = std::to_string(result_code.value());
|
res = std::to_string(result_code.value());
|
||||||
};
|
};
|
||||||
|
|
||||||
libbitcoin::explorer::config::transaction transaction(tx);
|
const libbitcoin::explorer::config::transaction transaction(tx);
|
||||||
|
|
||||||
libbitcoin::chain::transaction trx;
|
|
||||||
|
|
||||||
// This validates the tx, submits it to local tx pool, and notifies peers.
|
// This validates the tx, submits it to local tx pool, and notifies peers.
|
||||||
obelisk_client.transaction_pool_broadcast(error_handler, result_handler, transaction);
|
obelisk_client.transaction_pool_broadcast(error_handler, result_handler, transaction);
|
||||||
|
|
@ -78,22 +76,22 @@ std::string libbitcoin_client::send_transaction(std::string tx) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
libbitcoin::chain::output::list libbitcoin_client::get_transaction(std::string tx_id, std::string &tx_hash, uint32_t &confirmitions) {
|
libbitcoin::chain::output::list libbitcoin_client::get_transaction(const std::string &tx_id, std::string &tx_hash, uint32_t &confirmitions) {
|
||||||
|
|
||||||
libbitcoin::chain::output::list outs;
|
libbitcoin::chain::output::list outs;
|
||||||
|
|
||||||
auto error_handler = [&](const std::error_code &ec) {
|
auto error_handler = [&tx_id](const std::error_code &ec) {
|
||||||
elog("error on fetch_trx_by_hash: ${hash} ${error_code}", ("hash", tx_id)("error_code", ec.message()));
|
elog("error on fetch_trx_by_hash: ${hash} ${error_code}", ("hash", tx_id)("error_code", ec.message()));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto transaction_handler = [&](const libbitcoin::chain::transaction &tx_handler) {
|
auto transaction_handler = [&tx_hash, &confirmitions, &outs](const libbitcoin::chain::transaction &tx_handler) {
|
||||||
tx_hash = libbitcoin::config::hash256(tx_handler.hash(false)).to_string();
|
tx_hash = libbitcoin::config::hash256(tx_handler.hash(false)).to_string();
|
||||||
// TODO try to find this value (confirmitions)
|
// TODO try to find this value (confirmitions)
|
||||||
confirmitions = 1;
|
confirmitions = 1;
|
||||||
outs = tx_handler.outputs();
|
outs = tx_handler.outputs();
|
||||||
};
|
};
|
||||||
|
|
||||||
libbitcoin::hash_digest hash = libbitcoin::config::hash256(tx_id);
|
const libbitcoin::hash_digest hash = libbitcoin::config::hash256(tx_id);
|
||||||
|
|
||||||
// obelisk_client.blockchain_fetch_transaction (error_handler, transaction_handler,hash);
|
// obelisk_client.blockchain_fetch_transaction (error_handler, transaction_handler,hash);
|
||||||
obelisk_client.blockchain_fetch_transaction2(error_handler, transaction_handler, hash);
|
obelisk_client.blockchain_fetch_transaction2(error_handler, transaction_handler, hash);
|
||||||
|
|
@ -103,14 +101,14 @@ libbitcoin::chain::output::list libbitcoin_client::get_transaction(std::string t
|
||||||
return outs;
|
return outs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<list_unspent_replay> libbitcoin_client::listunspent(std::string address, double amount) {
|
std::vector<list_unspent_replay> libbitcoin_client::listunspent(const std::string &address, double amount) {
|
||||||
std::vector<list_unspent_replay> result;
|
std::vector<list_unspent_replay> result;
|
||||||
|
|
||||||
auto error_handler = [&](const std::error_code &ec) {
|
auto error_handler = [](const std::error_code &ec) {
|
||||||
elog("error on list_unspent ${error_code}", ("error_code", ec.message()));
|
elog("error on list_unspent ${error_code}", ("error_code", ec.message()));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto replay_handler = [&](const libbitcoin::chain::points_value &points) {
|
auto replay_handler = [&result](const libbitcoin::chain::points_value &points) {
|
||||||
for (auto &point : points.points) {
|
for (auto &point : points.points) {
|
||||||
list_unspent_replay output;
|
list_unspent_replay output;
|
||||||
output.hash = libbitcoin::config::hash256(point.hash()).to_string();
|
output.hash = libbitcoin::config::hash256(point.hash()).to_string();
|
||||||
|
|
@ -120,8 +118,8 @@ std::vector<list_unspent_replay> libbitcoin_client::listunspent(std::string addr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
libbitcoin::wallet::payment_address payment_address(address);
|
const libbitcoin::wallet::payment_address payment_address(address);
|
||||||
uint64_t satoshi = 100000000 * amount;
|
const auto satoshi = static_cast<uint64_t>(100000000 * amount);
|
||||||
|
|
||||||
obelisk_client.blockchain_fetch_unspent_outputs(error_handler,
|
obelisk_client.blockchain_fetch_unspent_outputs(error_handler,
|
||||||
replay_handler, payment_address, satoshi, libbitcoin::wallet::select_outputs::algorithm::individual);
|
replay_handler, payment_address, satoshi, libbitcoin::wallet::select_outputs::algorithm::individual);
|
||||||
|
|
@ -135,12 +133,12 @@ bool libbitcoin_client::get_is_test_net() {
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
auto error_handler = [&](const std::error_code &ec) {
|
auto error_handler = [](const std::error_code &ec) {
|
||||||
elog("error on fetching genesis block ${error_code}", ("error_code", ec.message()));
|
elog("error on fetching genesis block ${error_code}", ("error_code", ec.message()));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto block_header_handler = [&](const libbitcoin::chain::header &block_header) {
|
auto block_header_handler = [&result](const libbitcoin::chain::header &block_header) {
|
||||||
std::string hash_str = libbitcoin::config::hash256(block_header.hash()).to_string();
|
const std::string hash_str = libbitcoin::config::hash256(block_header.hash()).to_string();
|
||||||
if (hash_str == GENESIS_TESTNET_HASH || hash_str == GENESIS_REGTEST_HASH) {
|
if (hash_str == GENESIS_TESTNET_HASH || hash_str == GENESIS_REGTEST_HASH) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +150,7 @@ bool libbitcoin_client::get_is_test_net() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t libbitcoin_client::get_fee_from_trx(libbitcoin::chain::transaction trx) {
|
uint64_t libbitcoin_client::get_fee_from_trx(const libbitcoin::chain::transaction &trx) {
|
||||||
bool general_fee_est_error = false;
|
bool general_fee_est_error = false;
|
||||||
|
|
||||||
if (trx.is_coinbase()) {
|
if (trx.is_coinbase()) {
|
||||||
|
|
@ -169,15 +167,15 @@ uint64_t libbitcoin_client::get_fee_from_trx(libbitcoin::chain::transaction trx)
|
||||||
|
|
||||||
// fetch the trx to get total input value
|
// fetch the trx to get total input value
|
||||||
uint64_t total_input_value = 0;
|
uint64_t total_input_value = 0;
|
||||||
auto transaction_handler = [&](const libbitcoin::chain::transaction &tx_handler) {
|
auto transaction_handler = [&prev_out_trxs, &total_input_value](const libbitcoin::chain::transaction &tx_handler) {
|
||||||
std::vector<uint32_t> indexes = prev_out_trxs[tx_handler.hash()];
|
std::vector<uint32_t> indexes = prev_out_trxs[tx_handler.hash()];
|
||||||
|
|
||||||
for (auto &index : indexes) {
|
for (const auto &index : indexes) {
|
||||||
total_input_value += tx_handler.outputs()[index].value();
|
total_input_value += tx_handler.outputs()[index].value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto error_handler = [&](const std::error_code &ec) {
|
auto error_handler = [&general_fee_est_error](const std::error_code &ec) {
|
||||||
elog("error on fetching trx ${error_code}", ("error_code", ec.message()));
|
elog("error on fetching trx ${error_code}", ("error_code", ec.message()));
|
||||||
general_fee_est_error = true;
|
general_fee_est_error = true;
|
||||||
};
|
};
|
||||||
|
|
@ -201,12 +199,12 @@ uint64_t libbitcoin_client::get_fee_from_trx(libbitcoin::chain::transaction trx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t libbitcoin_client::get_average_fee_from_trxs(std::vector<libbitcoin::chain::transaction> trx_list) {
|
uint64_t libbitcoin_client::get_average_fee_from_trxs(const std::vector<libbitcoin::chain::transaction> &trx_list) {
|
||||||
std::vector<uint64_t> fee_per_trxs;
|
std::vector<uint64_t> fee_per_trxs;
|
||||||
|
|
||||||
for (auto &trx : trx_list) {
|
for (auto &trx : trx_list) {
|
||||||
|
|
||||||
uint64_t fee = get_fee_from_trx(trx);
|
const uint64_t fee = get_fee_from_trx(trx);
|
||||||
if (fee > 0) {
|
if (fee > 0) {
|
||||||
fee_per_trxs.emplace_back(fee);
|
fee_per_trxs.emplace_back(fee);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
#include <bitcoin/system/chain/block.hpp>
|
#include <bitcoin/system/chain/block.hpp>
|
||||||
|
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#define LIBBITCOIN_SERVER_TIMEOUT (10)
|
#define LIBBITCOIN_SERVER_TIMEOUT (10)
|
||||||
#define LIBBITCOIN_SERVER_RETRIES (100)
|
#define LIBBITCOIN_SERVER_RETRIES (100)
|
||||||
#define DEAFULT_LIBBITCOIN_TRX_FEE (20000)
|
#define DEAFULT_LIBBITCOIN_TRX_FEE (20000)
|
||||||
#define MAX_TRXS_IN_MEMORY_POOL (30000)
|
#define MAX_TRXS_IN_MEMORY_POOL (10000)
|
||||||
#define MIN_TRXS_IN_BUCKET (100)
|
#define MIN_TRXS_IN_BUCKET (100)
|
||||||
|
#define MAX_THREADS (5)
|
||||||
|
|
||||||
#define GENESIS_MAINNET_HASH "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
#define GENESIS_MAINNET_HASH "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||||
#define GENESIS_TESTNET_HASH "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
#define GENESIS_TESTNET_HASH "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
|
|
||||||
namespace graphene { namespace peerplays_sidechain {
|
namespace graphene { namespace peerplays_sidechain {
|
||||||
|
|
||||||
typedef std::function<void(const libbitcoin::chain::block &)>
|
|
||||||
block_update_handler;
|
|
||||||
|
|
||||||
struct list_unspent_replay {
|
struct list_unspent_replay {
|
||||||
std::string hash;
|
std::string hash;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
|
@ -30,12 +27,12 @@ struct list_unspent_replay {
|
||||||
|
|
||||||
class libbitcoin_client {
|
class libbitcoin_client {
|
||||||
public:
|
public:
|
||||||
libbitcoin_client(std::string url);
|
explicit libbitcoin_client(const std::string &url);
|
||||||
std::string send_transaction(const std::string tx);
|
std::string send_transaction(const std::string &tx);
|
||||||
libbitcoin::chain::output::list get_transaction(std::string tx_id, std::string &tx_hash, uint32_t &confirmitions);
|
libbitcoin::chain::output::list get_transaction(const std::string &tx_id, std::string &tx_hash, uint32_t &confirmitions);
|
||||||
std::vector<list_unspent_replay> listunspent(std::string address, double amount);
|
std::vector<list_unspent_replay> listunspent(const std::string &address, double amount);
|
||||||
uint64_t get_average_fee_from_trxs(std::vector<libbitcoin::chain::transaction> trx_list);
|
uint64_t get_average_fee_from_trxs(const std::vector<libbitcoin::chain::transaction> &trx_list);
|
||||||
uint64_t get_fee_from_trx(libbitcoin::chain::transaction trx);
|
uint64_t get_fee_from_trx(const libbitcoin::chain::transaction &trx);
|
||||||
bool get_is_test_net();
|
bool get_is_test_net();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ public:
|
||||||
std::string label;
|
std::string label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtual ~bitcoin_client_base() = default;
|
||||||
virtual uint64_t estimatesmartfee(uint16_t conf_target = 1) = 0;
|
virtual uint64_t estimatesmartfee(uint16_t conf_target = 1) = 0;
|
||||||
virtual std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2) = 0;
|
virtual std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2) = 0;
|
||||||
virtual btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) = 0;
|
virtual btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) = 0;
|
||||||
|
|
@ -70,8 +71,8 @@ public:
|
||||||
virtual std::string getblockchaininfo() = 0;
|
virtual std::string getblockchaininfo() = 0;
|
||||||
virtual std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) = 0;
|
virtual std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) = 0;
|
||||||
virtual std::string sendrawtransaction(const std::string &tx_hex) = 0;
|
virtual std::string sendrawtransaction(const std::string &tx_hex) = 0;
|
||||||
virtual void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true) {
|
virtual void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true){
|
||||||
;
|
//! Default implementation does nothing
|
||||||
};
|
};
|
||||||
virtual std::string loadwallet(const std::string &filename) {
|
virtual std::string loadwallet(const std::string &filename) {
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -96,44 +97,37 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
class bitcoin_rpc_client : public bitcoin_client_base, public rpc_client {
|
class bitcoin_rpc_client : public bitcoin_client_base, public rpc_client {
|
||||||
public:
|
|
||||||
public:
|
public:
|
||||||
bitcoin_rpc_client(const std::vector<rpc_credentials> &_credentials, bool _debug_rpc_calls, bool _simulate_connection_reselection);
|
bitcoin_rpc_client(const std::vector<rpc_credentials> &_credentials, bool _debug_rpc_calls, bool _simulate_connection_reselection);
|
||||||
|
uint64_t estimatesmartfee(uint16_t conf_target = 1) final;
|
||||||
uint64_t estimatesmartfee(uint16_t conf_target = 1);
|
std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2) final;
|
||||||
std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2);
|
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) final;
|
||||||
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false);
|
void getnetworkinfo() final;
|
||||||
void getnetworkinfo();
|
std::string getblockchaininfo() final;
|
||||||
std::string getblockchaininfo();
|
void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true) final;
|
||||||
void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true);
|
|
||||||
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);
|
||||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) final;
|
||||||
std::string loadwallet(const std::string &filename);
|
std::string loadwallet(const std::string &filename) final;
|
||||||
std::string sendrawtransaction(const std::string &tx_hex);
|
std::string sendrawtransaction(const std::string &tx_hex) final;
|
||||||
std::string walletlock();
|
std::string walletlock() final;
|
||||||
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60);
|
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60) final;
|
||||||
|
|
||||||
virtual uint64_t ping(rpc_connection &conn) const override;
|
uint64_t ping(rpc_connection &conn) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string ip;
|
|
||||||
std::string user;
|
|
||||||
std::string password;
|
|
||||||
std::string wallet_name;
|
|
||||||
std::string wallet_password;
|
|
||||||
uint32_t bitcoin_major_version;
|
uint32_t bitcoin_major_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
class bitcoin_libbitcoin_client : public bitcoin_client_base, public libbitcoin_client {
|
class bitcoin_libbitcoin_client : public bitcoin_client_base, public libbitcoin_client {
|
||||||
public:
|
public:
|
||||||
bitcoin_libbitcoin_client(std::string url);
|
explicit bitcoin_libbitcoin_client(const std::string &url);
|
||||||
uint64_t estimatesmartfee(uint16_t conf_target = 1);
|
uint64_t estimatesmartfee(uint16_t conf_target = 1) final;
|
||||||
std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2);
|
std::vector<info_for_vin> getblock(const block_data &block, int32_t verbosity = 2) final;
|
||||||
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false);
|
btc_tx getrawtransaction(const std::string &txid, const bool verbose = false) final;
|
||||||
void getnetworkinfo();
|
void getnetworkinfo() final;
|
||||||
std::string getblockchaininfo();
|
std::string getblockchaininfo() final;
|
||||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999) final;
|
||||||
std::string sendrawtransaction(const std::string &tx_hex);
|
std::string sendrawtransaction(const std::string &tx_hex) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_test_net = false;
|
bool is_test_net = false;
|
||||||
|
|
@ -145,13 +139,13 @@ private:
|
||||||
|
|
||||||
class zmq_listener_base {
|
class zmq_listener_base {
|
||||||
public:
|
public:
|
||||||
virtual ~zmq_listener_base(){};
|
zmq_listener_base(const std::string &_ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0) :
|
||||||
zmq_listener_base(std::string _ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0) {
|
ip(_ip),
|
||||||
ip = _ip;
|
block_zmq_port(_block_zmq_port),
|
||||||
block_zmq_port = _block_zmq_port;
|
trx_zmq_port(_trx_zmq_port),
|
||||||
trx_zmq_port = _trx_zmq_port;
|
stopped(false){};
|
||||||
stopped = false;
|
virtual ~zmq_listener_base() = default;
|
||||||
};
|
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
boost::signals2::signal<void(const block_data &)> block_event_received;
|
boost::signals2::signal<void(const block_data &)> block_event_received;
|
||||||
boost::signals2::signal<void(const libbitcoin::chain::transaction &)> trx_event_received;
|
boost::signals2::signal<void(const libbitcoin::chain::transaction &)> trx_event_received;
|
||||||
|
|
@ -167,9 +161,9 @@ protected:
|
||||||
|
|
||||||
class zmq_listener : public zmq_listener_base {
|
class zmq_listener : public zmq_listener_base {
|
||||||
public:
|
public:
|
||||||
zmq_listener(std::string _ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0);
|
zmq_listener(const std::string &_ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port = 0);
|
||||||
virtual ~zmq_listener();
|
~zmq_listener() final;
|
||||||
void start();
|
void start() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_zmq();
|
void handle_zmq();
|
||||||
|
|
@ -181,9 +175,9 @@ private:
|
||||||
|
|
||||||
class zmq_listener_libbitcoin : public zmq_listener_base {
|
class zmq_listener_libbitcoin : public zmq_listener_base {
|
||||||
public:
|
public:
|
||||||
zmq_listener_libbitcoin(std::string _ip, uint32_t _block_zmq_port = 9093, uint32_t _trx_zmq_port = 9094);
|
zmq_listener_libbitcoin(const std::string &_ip, uint32_t _block_zmq_port = 9093, uint32_t _trx_zmq_port = 9094);
|
||||||
virtual ~zmq_listener_libbitcoin();
|
~zmq_listener_libbitcoin() final;
|
||||||
void start();
|
void start() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_block();
|
void handle_block();
|
||||||
|
|
@ -192,6 +186,7 @@ private:
|
||||||
libbitcoin::protocol::zmq::context block_context;
|
libbitcoin::protocol::zmq::context block_context;
|
||||||
libbitcoin::protocol::zmq::socket block_socket;
|
libbitcoin::protocol::zmq::socket block_socket;
|
||||||
libbitcoin::protocol::zmq::poller block_poller;
|
libbitcoin::protocol::zmq::poller block_poller;
|
||||||
|
|
||||||
libbitcoin::protocol::zmq::context trx_context;
|
libbitcoin::protocol::zmq::context trx_context;
|
||||||
libbitcoin::protocol::zmq::socket trx_socket;
|
libbitcoin::protocol::zmq::socket trx_socket;
|
||||||
libbitcoin::protocol::zmq::poller trx_poller;
|
libbitcoin::protocol::zmq::poller trx_poller;
|
||||||
|
|
@ -202,17 +197,17 @@ private:
|
||||||
class sidechain_net_handler_bitcoin : public sidechain_net_handler {
|
class sidechain_net_handler_bitcoin : public sidechain_net_handler {
|
||||||
public:
|
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();
|
~sidechain_net_handler_bitcoin() final;
|
||||||
|
|
||||||
bool process_proposal(const proposal_object &po);
|
bool process_proposal(const proposal_object &po) final;
|
||||||
void process_primary_wallet();
|
void process_primary_wallet() final;
|
||||||
void process_sidechain_addresses();
|
void process_sidechain_addresses() final;
|
||||||
bool process_deposit(const son_wallet_deposit_object &swdo);
|
bool process_deposit(const son_wallet_deposit_object &swdo) final;
|
||||||
bool process_withdrawal(const son_wallet_withdraw_object &swwo);
|
bool process_withdrawal(const son_wallet_withdraw_object &swwo) final;
|
||||||
std::string process_sidechain_transaction(const sidechain_transaction_object &sto);
|
std::string process_sidechain_transaction(const sidechain_transaction_object &sto) final;
|
||||||
std::string send_sidechain_transaction(const sidechain_transaction_object &sto);
|
std::string send_sidechain_transaction(const sidechain_transaction_object &sto) final;
|
||||||
bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount);
|
bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) final;
|
||||||
virtual optional<asset> estimate_withdrawal_transaction_fee() const override;
|
optional<asset> estimate_withdrawal_transaction_fee() const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<rpc_credentials> _rpc_credentials;
|
std::vector<rpc_credentials> _rpc_credentials;
|
||||||
|
|
@ -229,10 +224,16 @@ private:
|
||||||
fc::future<void> on_changed_objects_task;
|
fc::future<void> on_changed_objects_task;
|
||||||
|
|
||||||
bitcoin::bitcoin_address::network network_type;
|
bitcoin::bitcoin_address::network network_type;
|
||||||
uint32_t bitcoin_major_version;
|
|
||||||
|
|
||||||
std::mutex event_handler_mutex;
|
std::mutex event_handler_mutex;
|
||||||
typedef std::lock_guard<decltype(event_handler_mutex)> scoped_lock;
|
using scoped_lock = std::lock_guard<decltype(event_handler_mutex)>;
|
||||||
|
|
||||||
|
boost::asio::io_context io_context_block;
|
||||||
|
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work_guard_block;
|
||||||
|
boost::thread_group thread_pool_block;
|
||||||
|
boost::asio::io_context io_context_trx;
|
||||||
|
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work_guard_trx;
|
||||||
|
boost::thread_group thread_pool_trx;
|
||||||
|
|
||||||
std::string create_primary_wallet_address(const std::vector<son_sidechain_info> &son_pubkeys);
|
std::string create_primary_wallet_address(const std::vector<son_sidechain_info> &son_pubkeys);
|
||||||
|
|
||||||
|
|
@ -240,7 +241,7 @@ private:
|
||||||
std::string create_deposit_transaction(const son_wallet_deposit_object &swdo);
|
std::string create_deposit_transaction(const son_wallet_deposit_object &swdo);
|
||||||
std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo);
|
std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo);
|
||||||
|
|
||||||
std::string create_transaction(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs, std::string &redeem_script);
|
std::string create_transaction(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs, const std::string &redeem_script);
|
||||||
std::string sign_transaction(const sidechain_transaction_object &sto);
|
std::string sign_transaction(const sidechain_transaction_object &sto);
|
||||||
std::string send_transaction(const sidechain_transaction_object &sto);
|
std::string send_transaction(const sidechain_transaction_object &sto);
|
||||||
|
|
||||||
|
|
@ -249,6 +250,8 @@ private:
|
||||||
std::string get_redeemscript_for_userdeposit(const std::string &user_address);
|
std::string get_redeemscript_for_userdeposit(const std::string &user_address);
|
||||||
void on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
void on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||||
void on_changed_objects_cb(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
void on_changed_objects_cb(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||||
|
|
||||||
|
void init_thread_pool(boost::asio::io_context &io_context, boost::thread_group &thread_pool, int num_threads);
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace graphene::peerplays_sidechain
|
}} // namespace graphene::peerplays_sidechain
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@ uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<info_for_vin> bitcoin_rpc_client::getblock(const block_data &block, int32_t verbosity) {
|
std::vector<info_for_vin> bitcoin_rpc_client::getblock(const block_data &block, int32_t verbosity) {
|
||||||
std::string params = std::string("[\"") + block.block_hash + std::string("\",") + std::to_string(verbosity) + std::string("]");
|
const std::string params = std::string("[\"") + block.block_hash + std::string("\",") + std::to_string(verbosity) + std::string("]");
|
||||||
std::string str = send_post_request("getblock", params, debug_rpc_calls);
|
const std::string str = send_post_request("getblock", params, debug_rpc_calls);
|
||||||
std::vector<info_for_vin> result;
|
std::vector<info_for_vin> result;
|
||||||
|
|
||||||
if (str.empty()) {
|
if (str.empty()) {
|
||||||
|
|
@ -66,7 +66,7 @@ std::vector<info_for_vin> bitcoin_rpc_client::getblock(const block_data &block,
|
||||||
boost::property_tree::ptree json;
|
boost::property_tree::ptree json;
|
||||||
boost::property_tree::read_json(ss, json);
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
auto json_result = json.get_child_optional("result");
|
const auto json_result = json.get_child_optional("result");
|
||||||
|
|
||||||
for (const auto &tx_child : json_result.get().get_child("tx")) {
|
for (const auto &tx_child : json_result.get().get_child("tx")) {
|
||||||
const auto &tx = tx_child.second;
|
const auto &tx = tx_child.second;
|
||||||
|
|
@ -103,8 +103,8 @@ std::vector<info_for_vin> bitcoin_rpc_client::getblock(const block_data &block,
|
||||||
}
|
}
|
||||||
|
|
||||||
void bitcoin_rpc_client::getnetworkinfo() {
|
void bitcoin_rpc_client::getnetworkinfo() {
|
||||||
std::string params = std::string("[]");
|
static const std::string params = std::string("[]");
|
||||||
std::string str = send_post_request("getnetworkinfo", params, debug_rpc_calls);
|
const std::string str = send_post_request("getnetworkinfo", params, debug_rpc_calls);
|
||||||
|
|
||||||
std::stringstream network_info_ss(str);
|
std::stringstream network_info_ss(str);
|
||||||
boost::property_tree::ptree network_info_json;
|
boost::property_tree::ptree network_info_json;
|
||||||
|
|
@ -115,8 +115,8 @@ void bitcoin_rpc_client::getnetworkinfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
btc_tx bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) {
|
btc_tx bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) {
|
||||||
std::string params = std::string("[\"") + txid + std::string("\",") + (verbose ? "true" : "false") + std::string("]");
|
const std::string params = std::string("[\"") + txid + std::string("\",") + (verbose ? "true" : "false") + std::string("]");
|
||||||
std::string str = send_post_request("getrawtransaction", params, debug_rpc_calls);
|
const std::string str = send_post_request("getrawtransaction", params, debug_rpc_calls);
|
||||||
|
|
||||||
btc_tx tx;
|
btc_tx tx;
|
||||||
|
|
||||||
|
|
@ -126,10 +126,10 @@ btc_tx bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool
|
||||||
|
|
||||||
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");
|
const std::string tx_txid = tx_json.get<std::string>("result.txid");
|
||||||
uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations");
|
const uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations");
|
||||||
|
|
||||||
tx.tx_txid = tx_txid;
|
tx.tx_txid = std::move(tx_txid);
|
||||||
tx.tx_confirmations = tx_confirmations;
|
tx.tx_confirmations = tx_confirmations;
|
||||||
|
|
||||||
for (auto &input : tx_json.get_child("result.vout")) {
|
for (auto &input : tx_json.get_child("result.vout")) {
|
||||||
|
|
@ -332,14 +332,14 @@ bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bitcoin_libbitcoin_client::bitcoin_libbitcoin_client(std::string url) :
|
bitcoin_libbitcoin_client::bitcoin_libbitcoin_client(const std::string &url) :
|
||||||
libbitcoin_client(url) {
|
libbitcoin_client(url) {
|
||||||
|
|
||||||
estimate_fee_ext = std::unique_ptr<estimate_fee_external>(new estimate_fee_external());
|
estimate_fee_ext = std::unique_ptr<estimate_fee_external>(new estimate_fee_external());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t bitcoin_libbitcoin_client::estimatesmartfee(uint16_t conf_target) {
|
uint64_t bitcoin_libbitcoin_client::estimatesmartfee(uint16_t conf_target) {
|
||||||
std::vector<std::pair<std::string, uint64_t>> fees = estimate_fee_ext->get_fee_external(conf_target);
|
const std::vector<std::pair<std::string, uint64_t>> fees = estimate_fee_ext->get_fee_external(conf_target);
|
||||||
std::vector<uint64_t> accumulated_fees;
|
std::vector<uint64_t> accumulated_fees;
|
||||||
for (auto &external_fees : fees) {
|
for (auto &external_fees : fees) {
|
||||||
if (external_fees.second != 0) {
|
if (external_fees.second != 0) {
|
||||||
|
|
@ -357,28 +357,30 @@ uint64_t bitcoin_libbitcoin_client::estimatesmartfee(uint16_t conf_target) {
|
||||||
|
|
||||||
std::vector<info_for_vin> bitcoin_libbitcoin_client::getblock(const block_data &block, int32_t verbosity) {
|
std::vector<info_for_vin> bitcoin_libbitcoin_client::getblock(const block_data &block, int32_t verbosity) {
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lck(libbitcoin_event_mutex);
|
{
|
||||||
|
std::unique_lock<std::mutex> lck(libbitcoin_event_mutex);
|
||||||
|
|
||||||
// estimate fee
|
// estimate fee
|
||||||
const auto &block_trxs = block.block.transactions();
|
const auto &block_trxs = block.block.transactions();
|
||||||
std::vector<libbitcoin::chain::transaction> bucket_trxs;
|
std::vector<libbitcoin::chain::transaction> bucket_trxs;
|
||||||
for (auto &mem_pool_trx : trx_memory_pool) {
|
for (auto &mem_pool_trx : trx_memory_pool) {
|
||||||
for (auto &trx : block_trxs) {
|
for (auto &trx : block_trxs) {
|
||||||
if (mem_pool_trx.hash() == trx.hash()) {
|
if (mem_pool_trx.hash() == trx.hash()) {
|
||||||
bucket_trxs.emplace_back(mem_pool_trx);
|
bucket_trxs.emplace_back(mem_pool_trx);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t average_fee = get_average_fee_from_trxs(bucket_trxs);
|
const uint64_t average_fee = get_average_fee_from_trxs(bucket_trxs);
|
||||||
if (average_fee > 0 && bucket_trxs.size() >= MIN_TRXS_IN_BUCKET) {
|
if (average_fee > 0 && bucket_trxs.size() >= MIN_TRXS_IN_BUCKET) {
|
||||||
current_internal_fee = average_fee;
|
current_internal_fee = average_fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We could consider accumulation which could spread to multiple blocks for better metric
|
// We could consider accumulation which could spread to multiple blocks for better metric
|
||||||
// for now we only keep tracking for not confirmed transaction until we get next block
|
// for now we only keep tracking for not confirmed transaction until we get next block
|
||||||
trx_memory_pool.clear();
|
trx_memory_pool.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<info_for_vin> result;
|
std::vector<info_for_vin> result;
|
||||||
|
|
||||||
|
|
@ -481,8 +483,8 @@ std::string bitcoin_libbitcoin_client::getblockchaininfo() {
|
||||||
std::vector<btc_txout> bitcoin_libbitcoin_client::listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf, const uint32_t maxconf) {
|
std::vector<btc_txout> bitcoin_libbitcoin_client::listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf, const uint32_t maxconf) {
|
||||||
|
|
||||||
std::vector<btc_txout> result;
|
std::vector<btc_txout> result;
|
||||||
std::vector<list_unspent_replay> outputs = listunspent(address, transfer_amount);
|
const std::vector<list_unspent_replay> outputs = listunspent(address, transfer_amount);
|
||||||
for (auto &output : outputs) {
|
for (const auto &output : outputs) {
|
||||||
btc_txout txo;
|
btc_txout txo;
|
||||||
txo.txid_ = output.hash;
|
txo.txid_ = output.hash;
|
||||||
txo.out_num_ = output.index;
|
txo.out_num_ = output.index;
|
||||||
|
|
@ -494,12 +496,12 @@ std::vector<btc_txout> bitcoin_libbitcoin_client::listunspent_by_address_and_amo
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string bitcoin_libbitcoin_client::sendrawtransaction(const std::string &tx_hex) {
|
std::string bitcoin_libbitcoin_client::sendrawtransaction(const std::string &tx_hex) {
|
||||||
std::string res = send_transaction(tx_hex);
|
const std::string res = send_transaction(tx_hex);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t bitcoin_rpc_client::ping(rpc_connection &conn) const {
|
uint64_t bitcoin_rpc_client::ping(rpc_connection &conn) const {
|
||||||
std::string str = send_post_request(conn, "getblockcount", "[]", debug_rpc_calls);
|
const std::string str = send_post_request(conn, "getblockcount", "[]", debug_rpc_calls);
|
||||||
if (str.length() > 0)
|
if (str.length() > 0)
|
||||||
return std::stoll(str);
|
return std::stoll(str);
|
||||||
return std::numeric_limits<uint64_t>::max();
|
return std::numeric_limits<uint64_t>::max();
|
||||||
|
|
@ -507,7 +509,7 @@ uint64_t bitcoin_rpc_client::ping(rpc_connection &conn) const {
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
zmq_listener::zmq_listener(std::string _ip, uint32_t _zmq_block_port, uint32_t _zmq_trx_port) :
|
zmq_listener::zmq_listener(const std::string &_ip, uint32_t _zmq_block_port, uint32_t _zmq_trx_port) :
|
||||||
zmq_listener_base(_ip, _zmq_block_port, _zmq_trx_port),
|
zmq_listener_base(_ip, _zmq_block_port, _zmq_trx_port),
|
||||||
ctx(1),
|
ctx(1),
|
||||||
socket(ctx, ZMQ_SUB) {
|
socket(ctx, ZMQ_SUB) {
|
||||||
|
|
@ -577,7 +579,7 @@ void zmq_listener::handle_zmq() {
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
zmq_listener_libbitcoin::zmq_listener_libbitcoin(std::string _ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port) :
|
zmq_listener_libbitcoin::zmq_listener_libbitcoin(const std::string &_ip, uint32_t _block_zmq_port, uint32_t _trx_zmq_port) :
|
||||||
zmq_listener_base(_ip, _block_zmq_port, _trx_zmq_port),
|
zmq_listener_base(_ip, _block_zmq_port, _trx_zmq_port),
|
||||||
block_socket(block_context, libbitcoin::protocol::zmq::socket::role::subscriber),
|
block_socket(block_context, libbitcoin::protocol::zmq::socket::role::subscriber),
|
||||||
trx_socket(trx_context, libbitcoin::protocol::zmq::socket::role::subscriber) {
|
trx_socket(trx_context, libbitcoin::protocol::zmq::socket::role::subscriber) {
|
||||||
|
|
@ -590,7 +592,7 @@ zmq_listener_libbitcoin::~zmq_listener_libbitcoin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void zmq_listener_libbitcoin::start() {
|
void zmq_listener_libbitcoin::start() {
|
||||||
std::string endpoint_address = "tcp://" + ip;
|
const std::string endpoint_address = "tcp://" + ip;
|
||||||
|
|
||||||
libbitcoin::config::endpoint block_address(endpoint_address, block_zmq_port);
|
libbitcoin::config::endpoint block_address(endpoint_address, block_zmq_port);
|
||||||
libbitcoin::config::endpoint trx_address(endpoint_address, trx_zmq_port);
|
libbitcoin::config::endpoint trx_address(endpoint_address, trx_zmq_port);
|
||||||
|
|
@ -662,18 +664,20 @@ void zmq_listener_libbitcoin::handle_block() {
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
|
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
|
||||||
sidechain_net_handler(sidechain_type::bitcoin, _plugin, options) {
|
sidechain_net_handler(sidechain_type::bitcoin, _plugin, options),
|
||||||
|
work_guard_block(io_context_block.get_executor()),
|
||||||
|
work_guard_trx(io_context_trx.get_executor()) {
|
||||||
|
|
||||||
if (options.count("debug-rpc-calls")) {
|
if (options.count("debug-rpc-calls")) {
|
||||||
debug_rpc_calls = options.at("debug-rpc-calls").as<bool>();
|
debug_rpc_calls = options.at("debug-rpc-calls").as<bool>();
|
||||||
}
|
}
|
||||||
bool simulate_connection_reselection = options.at("simulate-rpc-connection-reselection").as<bool>();
|
const bool simulate_connection_reselection = options.at("simulate-rpc-connection-reselection").as<bool>();
|
||||||
|
|
||||||
std::vector<std::string> ips = options.at("bitcoin-node-ip").as<std::vector<std::string>>();
|
const std::vector<std::string> ips = options.at("bitcoin-node-ip").as<std::vector<std::string>>();
|
||||||
bitcoin_node_zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>();
|
bitcoin_node_zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>();
|
||||||
uint32_t rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>();
|
const uint32_t rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>();
|
||||||
std::string rpc_user = options.at("bitcoin-node-rpc-user").as<std::string>();
|
const std::string rpc_user = options.at("bitcoin-node-rpc-user").as<std::string>();
|
||||||
std::string rpc_password = options.at("bitcoin-node-rpc-password").as<std::string>();
|
const std::string rpc_password = options.at("bitcoin-node-rpc-password").as<std::string>();
|
||||||
|
|
||||||
if (options.count("use-bitcoind-client")) {
|
if (options.count("use-bitcoind-client")) {
|
||||||
use_bitcoind_client = options.at("use-bitcoind-client").as<bool>();
|
use_bitcoind_client = options.at("use-bitcoind-client").as<bool>();
|
||||||
|
|
@ -732,7 +736,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
||||||
listener = std::unique_ptr<zmq_listener_libbitcoin>(new zmq_listener_libbitcoin(libbitcoin_server_ip, libbitcoin_block_zmq_port, libbitcoin_trx_zmq_port));
|
listener = std::unique_ptr<zmq_listener_libbitcoin>(new zmq_listener_libbitcoin(libbitcoin_server_ip, libbitcoin_block_zmq_port, libbitcoin_trx_zmq_port));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string chain_info = bitcoin_client->getblockchaininfo();
|
const std::string chain_info = bitcoin_client->getblockchaininfo();
|
||||||
|
|
||||||
using namespace bitcoin;
|
using namespace bitcoin;
|
||||||
network_type = bitcoin_address::network::mainnet;
|
network_type = bitcoin_address::network::mainnet;
|
||||||
|
|
@ -745,12 +749,15 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
||||||
|
|
||||||
bitcoin_client->getnetworkinfo();
|
bitcoin_client->getnetworkinfo();
|
||||||
|
|
||||||
|
init_thread_pool(io_context_block, thread_pool_block, MAX_THREADS);
|
||||||
|
init_thread_pool(io_context_trx, thread_pool_trx, MAX_THREADS);
|
||||||
|
|
||||||
listener->block_event_received.connect([this](const block_data &block_event_data) {
|
listener->block_event_received.connect([this](const block_data &block_event_data) {
|
||||||
std::thread(&sidechain_net_handler_bitcoin::block_handle_event, this, block_event_data).detach();
|
io_context_block.post(boost::bind(&sidechain_net_handler_bitcoin::block_handle_event, this, block_event_data));
|
||||||
});
|
});
|
||||||
|
|
||||||
listener->trx_event_received.connect([this](const libbitcoin::chain::transaction &trx_event_data) {
|
listener->trx_event_received.connect([this](const libbitcoin::chain::transaction &trx_event_data) {
|
||||||
std::thread(&sidechain_net_handler_bitcoin::trx_handle_event, this, trx_event_data).detach();
|
io_context_trx.post(boost::bind(&sidechain_net_handler_bitcoin::trx_handle_event, this, trx_event_data));
|
||||||
});
|
});
|
||||||
|
|
||||||
listener->start();
|
listener->start();
|
||||||
|
|
@ -761,6 +768,11 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
||||||
}
|
}
|
||||||
|
|
||||||
sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
||||||
|
work_guard_block.reset();
|
||||||
|
work_guard_trx.reset();
|
||||||
|
thread_pool_block.join_all();
|
||||||
|
thread_pool_trx.join_all();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (on_changed_objects_task.valid()) {
|
if (on_changed_objects_task.valid()) {
|
||||||
on_changed_objects_task.cancel_and_wait(__FUNCTION__);
|
on_changed_objects_task.cancel_and_wait(__FUNCTION__);
|
||||||
|
|
@ -1212,7 +1224,7 @@ bool sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_obj
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tx_str = create_deposit_transaction(swdo);
|
const std::string tx_str = create_deposit_transaction(swdo);
|
||||||
|
|
||||||
if (!tx_str.empty()) {
|
if (!tx_str.empty()) {
|
||||||
const chain::global_property_object &gpo = database.get_global_properties();
|
const chain::global_property_object &gpo = database.get_global_properties();
|
||||||
|
|
@ -1263,7 +1275,7 @@ bool sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tx_str = create_withdrawal_transaction(swwo);
|
const std::string tx_str = create_withdrawal_transaction(swwo);
|
||||||
|
|
||||||
if (!tx_str.empty()) {
|
if (!tx_str.empty()) {
|
||||||
const chain::global_property_object &gpo = database.get_global_properties();
|
const chain::global_property_object &gpo = database.get_global_properties();
|
||||||
|
|
@ -1327,7 +1339,7 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
btc_tx tx = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true);
|
const btc_tx tx = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true);
|
||||||
|
|
||||||
if (tx.tx_in_list.empty()) {
|
if (tx.tx_in_list.empty()) {
|
||||||
// This case will result with segmentation fault.
|
// This case will result with segmentation fault.
|
||||||
|
|
@ -1349,11 +1361,11 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
|
||||||
payment_type_address = payment_type::P2WSH;
|
payment_type_address = payment_type::P2WSH;
|
||||||
}
|
}
|
||||||
|
|
||||||
btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address);
|
const btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address);
|
||||||
|
|
||||||
std::string tx_txid = tx.tx_txid;
|
const std::string tx_txid = tx.tx_txid;
|
||||||
uint32_t tx_confirmations = tx.tx_confirmations;
|
const uint32_t tx_confirmations = tx.tx_confirmations;
|
||||||
std::string tx_address = addr.get_address();
|
const std::string tx_address = addr.get_address();
|
||||||
int64_t tx_amount = -1;
|
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()) {
|
||||||
|
|
@ -1397,14 +1409,14 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const s
|
||||||
if (use_bitcoind_client) {
|
if (use_bitcoind_client) {
|
||||||
payment_type_address = payment_type::P2WSH;
|
payment_type_address = payment_type::P2WSH;
|
||||||
}
|
}
|
||||||
btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address);
|
const btc_weighted_multisig_address addr(pubkey_weights, network_type, payment_type_address);
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << "{\"result\": {\"address\": \"" << addr.get_address() << "\", \"redeemScript\": \"" << fc::to_hex(addr.get_redeem_script()) << "\""
|
ss << "{\"result\": {\"address\": \"" << addr.get_address() << "\", \"redeemScript\": \"" << fc::to_hex(addr.get_redeem_script()) << "\""
|
||||||
<< "}, \"error\":null}";
|
<< "}, \"error\":null}";
|
||||||
|
|
||||||
std::string res = ss.str();
|
const std::string res = ss.str();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1423,8 +1435,8 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
|
||||||
std::stringstream prev_sw_ss(s);
|
std::stringstream prev_sw_ss(s);
|
||||||
boost::property_tree::ptree prev_sw_pt;
|
boost::property_tree::ptree prev_sw_pt;
|
||||||
boost::property_tree::read_json(prev_sw_ss, prev_sw_pt);
|
boost::property_tree::read_json(prev_sw_ss, prev_sw_pt);
|
||||||
std::string prev_pw_address = prev_sw_pt.get<std::string>("address");
|
const std::string prev_pw_address = prev_sw_pt.get<std::string>("address");
|
||||||
std::string prev_redeem_script = prev_sw_pt.get<std::string>("redeemScript");
|
const std::string prev_redeem_script = prev_sw_pt.get<std::string>("redeemScript");
|
||||||
|
|
||||||
if (prev_pw_address == new_sw_address) {
|
if (prev_pw_address == new_sw_address) {
|
||||||
wlog("BTC previous and new primary wallet addresses are same. No funds moving needed [from ${prev_sw} to ${new_sw_address}]", ("prev_swo", prev_swo.id)("active_sw", new_sw_address));
|
wlog("BTC previous and new primary wallet addresses are same. No funds moving needed [from ${prev_sw} to ${new_sw_address}]", ("prev_swo", prev_swo.id)("active_sw", new_sw_address));
|
||||||
|
|
@ -1465,18 +1477,18 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
// Get redeem script for deposit address
|
// Get redeem script for deposit address
|
||||||
std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_from);
|
const std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_from);
|
||||||
std::string pw_address_json = obj->addresses.find(sidechain)->second;
|
const std::string pw_address_json = obj->addresses.find(sidechain)->second;
|
||||||
|
|
||||||
std::stringstream ss(pw_address_json);
|
std::stringstream ss(pw_address_json);
|
||||||
boost::property_tree::ptree json;
|
boost::property_tree::ptree json;
|
||||||
boost::property_tree::read_json(ss, json);
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
std::string pw_address = json.get<std::string>("address");
|
const std::string pw_address = json.get<std::string>("address");
|
||||||
|
|
||||||
std::string txid = swdo.sidechain_transaction_id;
|
const std::string txid = swdo.sidechain_transaction_id;
|
||||||
std::string suid = swdo.sidechain_uid;
|
const std::string suid = swdo.sidechain_uid;
|
||||||
std::string nvout = suid.substr(suid.find_last_of("-") + 1);
|
const std::string nvout = suid.substr(suid.find_last_of("-") + 1);
|
||||||
uint64_t deposit_amount = swdo.sidechain_amount.value;
|
uint64_t deposit_amount = swdo.sidechain_amount.value;
|
||||||
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||||
const uint64_t min_fee_rate = 1000;
|
const uint64_t min_fee_rate = 1000;
|
||||||
|
|
@ -1488,7 +1500,7 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_
|
||||||
}
|
}
|
||||||
|
|
||||||
deposit_amount -= fee_rate; // Deduct minimum relay fee
|
deposit_amount -= fee_rate; // Deduct minimum relay fee
|
||||||
double transfer_amount = (double)deposit_amount / 100000000.0;
|
const double transfer_amount = (double)deposit_amount / 100000000.0;
|
||||||
|
|
||||||
std::vector<btc_txout> inputs;
|
std::vector<btc_txout> inputs;
|
||||||
fc::flat_map<std::string, double> outputs;
|
fc::flat_map<std::string, double> outputs;
|
||||||
|
|
@ -1512,14 +1524,14 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pw_address_json = obj->addresses.find(sidechain)->second;
|
const std::string pw_address_json = obj->addresses.find(sidechain)->second;
|
||||||
|
|
||||||
std::stringstream ss(pw_address_json);
|
std::stringstream ss(pw_address_json);
|
||||||
boost::property_tree::ptree json;
|
boost::property_tree::ptree json;
|
||||||
boost::property_tree::read_json(ss, json);
|
boost::property_tree::read_json(ss, json);
|
||||||
|
|
||||||
std::string pw_address = json.get<std::string>("address");
|
const std::string pw_address = json.get<std::string>("address");
|
||||||
std::string redeem_script = json.get<std::string>("redeemScript");
|
const std::string redeem_script = json.get<std::string>("redeemScript");
|
||||||
|
|
||||||
int64_t fee_rate = bitcoin_client->estimatesmartfee();
|
int64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||||
const int64_t min_fee_rate = 1000;
|
const int64_t min_fee_rate = 1000;
|
||||||
|
|
@ -1551,7 +1563,7 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s
|
||||||
return create_transaction(inputs, outputs, redeem_script);
|
return create_transaction(inputs, outputs, redeem_script);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::create_transaction(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs, std::string &redeem_script) {
|
std::string sidechain_net_handler_bitcoin::create_transaction(const std::vector<btc_txout> &inputs, const fc::flat_map<std::string, double> outputs, const std::string &redeem_script) {
|
||||||
using namespace bitcoin;
|
using namespace bitcoin;
|
||||||
|
|
||||||
bitcoin_transaction_builder tb;
|
bitcoin_transaction_builder tb;
|
||||||
|
|
@ -1570,15 +1582,15 @@ std::string sidechain_net_handler_bitcoin::create_transaction(const std::vector<
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto tx = tb.get_transaction();
|
const auto tx = tb.get_transaction();
|
||||||
std::string hex_tx = fc::to_hex(pack(tx));
|
const std::string hex_tx = fc::to_hex(pack(tx));
|
||||||
std::string tx_raw = write_transaction_data(hex_tx, in_amounts, redeem_script);
|
const std::string tx_raw = write_transaction_data(hex_tx, in_amounts, redeem_script);
|
||||||
return tx_raw;
|
return tx_raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sidechain_net_handler_bitcoin::sign_transaction(const sidechain_transaction_object &sto) {
|
std::string sidechain_net_handler_bitcoin::sign_transaction(const sidechain_transaction_object &sto) {
|
||||||
using namespace bitcoin;
|
using namespace bitcoin;
|
||||||
std::string pubkey = plugin.get_current_son_object(sidechain).sidechain_public_keys.at(sidechain);
|
const std::string pubkey = plugin.get_current_son_object(sidechain).sidechain_public_keys.at(sidechain);
|
||||||
std::string prvkey = get_private_key(pubkey);
|
const std::string prvkey = get_private_key(pubkey);
|
||||||
std::vector<uint64_t> in_amounts;
|
std::vector<uint64_t> in_amounts;
|
||||||
std::string tx_hex;
|
std::string tx_hex;
|
||||||
std::string redeem_script;
|
std::string redeem_script;
|
||||||
|
|
@ -1589,14 +1601,14 @@ std::string sidechain_net_handler_bitcoin::sign_transaction(const sidechain_tran
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
const auto secret = btc_private_key->get_secret();
|
const auto secret = btc_private_key->get_secret();
|
||||||
bitcoin::bytes privkey_signing(secret.data(), secret.data() + secret.data_size());
|
const bitcoin::bytes privkey_signing(secret.data(), secret.data() + secret.data_size());
|
||||||
|
|
||||||
read_transaction_data(sto.transaction, tx_hex, in_amounts, redeem_script);
|
read_transaction_data(sto.transaction, tx_hex, in_amounts, redeem_script);
|
||||||
|
|
||||||
bitcoin_transaction tx = unpack(parse_hex(tx_hex));
|
const bitcoin_transaction tx = unpack(parse_hex(tx_hex));
|
||||||
std::vector<bitcoin::bytes> redeem_scripts(tx.vin.size(), parse_hex(redeem_script));
|
const std::vector<bitcoin::bytes> redeem_scripts(tx.vin.size(), parse_hex(redeem_script));
|
||||||
auto sigs = sign_witness_transaction_part(tx, redeem_scripts, in_amounts, privkey_signing, btc_context(), 1);
|
auto sigs = sign_witness_transaction_part(tx, redeem_scripts, in_amounts, privkey_signing, btc_context(), 1);
|
||||||
std::string tx_signature = write_transaction_signatures(sigs);
|
const std::string tx_signature = write_transaction_signatures(sigs);
|
||||||
|
|
||||||
return tx_signature;
|
return tx_signature;
|
||||||
}
|
}
|
||||||
|
|
@ -1613,7 +1625,7 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
|
||||||
|
|
||||||
std::vector<bitcoin::bytes> redeem_scripts(tx.vin.size(), parse_hex(redeem_script));
|
std::vector<bitcoin::bytes> redeem_scripts(tx.vin.size(), parse_hex(redeem_script));
|
||||||
|
|
||||||
uint32_t inputs_number = in_amounts.size();
|
const uint32_t inputs_number = in_amounts.size();
|
||||||
vector<bitcoin::bytes> dummy;
|
vector<bitcoin::bytes> dummy;
|
||||||
dummy.resize(inputs_number);
|
dummy.resize(inputs_number);
|
||||||
// Organise weighted address signatures
|
// Organise weighted address signatures
|
||||||
|
|
@ -1645,8 +1657,8 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string final_tx_hex = fc::to_hex(pack(tx));
|
const std::string final_tx_hex = fc::to_hex(pack(tx));
|
||||||
std::string res = bitcoin_client->sendrawtransaction(final_tx_hex);
|
const std::string res = bitcoin_client->sendrawtransaction(final_tx_hex);
|
||||||
|
|
||||||
if (res.empty()) {
|
if (res.empty()) {
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -1657,7 +1669,7 @@ std::string sidechain_net_handler_bitcoin::send_transaction(const sidechain_tran
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::block_handle_event(const block_data &event_data) {
|
void sidechain_net_handler_bitcoin::block_handle_event(const block_data &event_data) {
|
||||||
|
|
||||||
auto vins = bitcoin_client->getblock(event_data);
|
const auto vins = bitcoin_client->getblock(event_data);
|
||||||
|
|
||||||
add_to_son_listener_log("BLOCK : " + event_data.block_hash);
|
add_to_son_listener_log("BLOCK : " + event_data.block_hash);
|
||||||
|
|
||||||
|
|
@ -1698,6 +1710,7 @@ void sidechain_net_handler_bitcoin::block_handle_event(const block_data &event_d
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::trx_handle_event(const libbitcoin::chain::transaction &trx_data) {
|
void sidechain_net_handler_bitcoin::trx_handle_event(const libbitcoin::chain::transaction &trx_data) {
|
||||||
|
|
||||||
bitcoin_client->import_trx_to_memory_pool(trx_data);
|
bitcoin_client->import_trx_to_memory_pool(trx_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1720,20 +1733,20 @@ std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(cons
|
||||||
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(son.public_key)));
|
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(son.public_key)));
|
||||||
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
|
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
|
||||||
}
|
}
|
||||||
auto user_pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(addr_itr->deposit_public_key)));
|
const auto user_pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(addr_itr->deposit_public_key)));
|
||||||
|
|
||||||
payment_type payment_type_address = payment_type::P2SH_WSH;
|
payment_type payment_type_address = payment_type::P2SH_WSH;
|
||||||
if (use_bitcoind_client) {
|
if (use_bitcoind_client) {
|
||||||
payment_type_address = payment_type::P2WSH;
|
payment_type_address = payment_type::P2WSH;
|
||||||
}
|
}
|
||||||
btc_one_or_weighted_multisig_address deposit_addr(user_pub_key, pubkey_weights, network_type, payment_type_address);
|
const btc_one_or_weighted_multisig_address deposit_addr(user_pub_key, pubkey_weights, network_type, payment_type_address);
|
||||||
|
|
||||||
return fc::to_hex(deposit_addr.get_redeem_script());
|
return fc::to_hex(deposit_addr.get_redeem_script());
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidechain_net_handler_bitcoin::on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
|
void sidechain_net_handler_bitcoin::on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
|
||||||
fc::time_point now = fc::time_point::now();
|
const fc::time_point now = fc::time_point::now();
|
||||||
int64_t time_to_next_changed_objects_processing = 5000;
|
const int64_t time_to_next_changed_objects_processing = 5000;
|
||||||
|
|
||||||
fc::time_point next_wakeup(now + fc::microseconds(time_to_next_changed_objects_processing));
|
fc::time_point next_wakeup(now + fc::microseconds(time_to_next_changed_objects_processing));
|
||||||
|
|
||||||
|
|
@ -1784,6 +1797,12 @@ void sidechain_net_handler_bitcoin::on_changed_objects_cb(const vector<object_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sidechain_net_handler_bitcoin::init_thread_pool(boost::asio::io_context &io_context, boost::thread_group &thread_pool, int num_threads) {
|
||||||
|
for (int i = 0; i < num_threads; ++i) {
|
||||||
|
thread_pool.create_thread(boost::bind(&boost::asio::io_context::run, &io_context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
}
|
}
|
||||||
} // namespace graphene::peerplays_sidechain
|
} // namespace graphene::peerplays_sidechain
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue