libbitcoin client work in progress

This commit is contained in:
hirunda 2022-09-06 14:12:01 +02:00
parent 789c0547cf
commit a47498f642
5 changed files with 202 additions and 18 deletions

3
libraries/plugins/peerplays_sidechain/CMakeLists.txt Executable file → Normal file
View file

@ -15,6 +15,7 @@ add_library( peerplays_sidechain
bitcoin/segwit_addr.cpp bitcoin/segwit_addr.cpp
bitcoin/utils.cpp bitcoin/utils.cpp
bitcoin/sign_bitcoin_transaction.cpp bitcoin/sign_bitcoin_transaction.cpp
bitcoin/libbitcoin_client.cpp
common/rpc_client.cpp common/rpc_client.cpp
common/utils.cpp common/utils.cpp
hive/asset.cpp hive/asset.cpp
@ -36,7 +37,7 @@ endif()
unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS) unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS)
unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE) unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE)
target_link_libraries( peerplays_sidechain PRIVATE curl graphene_plugin zmq ) target_link_libraries( peerplays_sidechain PRIVATE curl graphene_plugin zmq bitcoin-system bitcoin-network bitcoin-client )
target_include_directories( peerplays_sidechain target_include_directories( peerplays_sidechain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )

View file

@ -0,0 +1,87 @@
#include <graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp>
#include <system_error>
#include <bitcoin/system/config/hash256.hpp>
namespace graphene { namespace peerplays_sidechain {
libbitcoin_client::libbitcoin_client() :
obelisk_client(10, 100) {
libbitcoin::client::connection_type connection;
connection.retries = 100;
connection.server = libbitcoin::config::endpoint("tcp://localhost", 9091);
if (!obelisk_client.connect(connection)) {
//display_connection_failure(error, connection.server);
//return console_result::failure;
std::cout << "Can't connect" << std::endl;
}
}
void libbitcoin_client::send_transaction(std::string tx) {
// std::cout<<"Enter in function"<<std::endl;
// auto error_handler = [&](const std::error_code &ec) {
// std::cout << "Error code: " << ec << std::endl;
// };
// auto result_handler = [&](libbitcoin::code result_code) {
// std::cout << "result is: " << result_code << std::endl;
// };
// std::cout<<"Transaction: "<<tx<<std::endl;
// libbitcoin::explorer::config::transaction transaction(tx);
// // This validates the tx, submits it to local tx pool, and notifies peers.
// libbitcoin_client.transaction_pool_broadcast(error_handler, result_handler, transaction);
// libbitcoin_client.wait();
}
void libbitcoin_client::fetch_trx_by_address(std::string address, double amount) {
auto error_handler = [&](const std::error_code &ec) {
std::cout << "Error code: " << ec << std::endl;
};
auto history_handler = [&](const libbitcoin::chain::history::list &rows) {
for (auto &row : rows) {
std::cout << "LIB Hash: " << libbitcoin::config::hash256(row.output.hash()) << std::endl;
std::cout << "LIB Amount: " << row.value;
}
};
libbitcoin::wallet::payment_address payment_address(address);
obelisk_client.blockchain_fetch_history3(error_handler,
history_handler, address);
obelisk_client.wait();
}
std::vector<list_unspent_replay> libbitcoin_client::list_unspent(std::string address, double amount) {
std::vector<list_unspent_replay> result;
auto error_handler = [&](const std::error_code &ec) {
std::cout << "Error code: " << ec << std::endl;
};
auto replay_handler = [&](const libbitcoin::chain::points_value &points) {
for (auto &point : points.points) {
list_unspent_replay output;
output.hash = libbitcoin::config::hash256(point.hash()).to_string();
output.value = point.value();
output.index = point.index();
result.emplace_back(output);
}
};
libbitcoin::wallet::payment_address payment_address(address);
obelisk_client.blockchain_fetch_unspent_outputs(error_handler,
replay_handler, payment_address, 100000000, libbitcoin::wallet::select_outputs::algorithm::individual);
obelisk_client.wait();
return result;
}
}} // namespace graphene::peerplays_sidechain

View file

@ -0,0 +1,25 @@
#pragma once
#include <bitcoin/client/obelisk_client.hpp>
namespace graphene { namespace peerplays_sidechain {
struct list_unspent_replay {
std::string hash;
uint64_t value;
uint32_t index;
};
class libbitcoin_client {
public:
libbitcoin_client();
// test methods for libbitcoin
void send_transaction(std::string tx);
void fetch_trx_by_address(std::string address, double amount);
std::vector<list_unspent_replay> list_unspent(std::string address, double amount);
private:
libbitcoin::client::obelisk_client obelisk_client;
};
}} // namespace graphene::peerplays_sidechain

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp>
#include <graphene/peerplays_sidechain/common/rpc_client.hpp> #include <graphene/peerplays_sidechain/common/rpc_client.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp> #include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
@ -23,7 +24,7 @@ public:
uint64_t amount_; uint64_t amount_;
}; };
class bitcoin_rpc_client : public rpc_client { class bitcoin_client {
public: public:
enum class multi_type { enum class multi_type {
script, script,
@ -41,10 +42,20 @@ public:
std::string label; std::string label;
}; };
virtual uint64_t estimatesmartfee(uint16_t conf_target = 128) = 0;
virtual std::string getblock(const std::string &block_hash, int32_t verbosity = 2) = 0;
virtual std::string getrawtransaction(const std::string &txid, const bool verbose = false) = 0;
virtual std::string getnetworkinfo() = 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::string sendrawtransaction(const std::string &tx_hex) = 0;
};
class bitcoin_rpc_client : public bitcoin_client, public rpc_client {
public:
public: public:
bitcoin_rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls); bitcoin_rpc_client(std::string _url, std::string _user, std::string _password, bool _debug_rpc_calls);
std::string createwallet(const std::string &wallet_name);
uint64_t estimatesmartfee(uint16_t conf_target = 128); uint64_t estimatesmartfee(uint16_t conf_target = 128);
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 getrawtransaction(const std::string &txid, const bool verbose = false);
@ -60,13 +71,23 @@ public:
private: private:
std::string ip; std::string ip;
uint32_t rpc_port;
std::string user; std::string user;
std::string password; std::string password;
std::string wallet; std::string wallet;
std::string wallet_password; std::string wallet_password;
}; };
class bitcoin_libbitcoin_client : public bitcoin_client, public libbitcoin_client {
public:
uint64_t estimatesmartfee(uint16_t conf_target = 128);
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 getnetworkinfo();
std::string getblockchaininfo();
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::string sendrawtransaction(const std::string &tx_hex);
};
// ============================================================================= // =============================================================================
class zmq_listener { class zmq_listener {
@ -118,6 +139,7 @@ private:
std::string wallet_password; std::string wallet_password;
std::unique_ptr<bitcoin_rpc_client> bitcoin_client; std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
std::unique_ptr<bitcoin_libbitcoin_client> lib_bitcoin_client;
std::unique_ptr<zmq_listener> listener; std::unique_ptr<zmq_listener> listener;
fc::future<void> on_changed_objects_task; fc::future<void> on_changed_objects_task;

View file

@ -29,12 +29,6 @@ bitcoin_rpc_client::bitcoin_rpc_client(std::string _url, std::string _user, std:
rpc_client(_url, _user, _password, _debug_rpc_calls) { rpc_client(_url, _user, _password, _debug_rpc_calls) {
} }
std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) {
std::string params = std::string("[\"") + wallet_name + std::string("\"]");
std::string str = send_post_request("createwallet", params, debug_rpc_calls);
return str;
}
uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) { uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
std::string params = std::string("[") + std::to_string(conf_target) + std::string("]"); std::string params = std::string("[") + std::to_string(conf_target) + std::string("]");
std::string str = send_post_request("estimatesmartfee", params, debug_rpc_calls); std::string str = send_post_request("estimatesmartfee", params, debug_rpc_calls);
@ -251,6 +245,58 @@ bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_
return true; return true;
} }
uint64_t bitcoin_libbitcoin_client::estimatesmartfee(uint16_t conf_target) {
// TODO
return 0;
}
std::string bitcoin_libbitcoin_client::getblock(const std::string &block_hash, int32_t verbosity) {
// TODO
return std::string("");
}
std::string bitcoin_libbitcoin_client::getrawtransaction(const std::string &txid, const bool verbose) {
// TODO
return std::string("");
}
std::string bitcoin_libbitcoin_client::getnetworkinfo() {
// TODO
return std::string("");
}
std::string bitcoin_libbitcoin_client::getblockchaininfo() {
// TODO
return std::string("");
}
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<list_unspent_replay> outputs = list_unspent(address, 0);
uint8_t counter{0};
for (auto &output : outputs) {
btc_txout txo;
txo.txid_ = output.hash;
txo.out_num_ = output.index;
txo.amount_ = output.value;
result.push_back(txo);
}
std::cout << "libbitcoin: ===>" << std::endl;
for (auto &res : result) {
std::cout << "Hash: " << res.txid_ << " out_num: " << res.out_num_ << " amount: " << res.amount_ << std::endl;
}
std::cout << "==================================>" << std::endl;
return result;
}
std::string bitcoin_libbitcoin_client::sendrawtransaction(const std::string &tx_hex) {
// TODO
return std::string("");
}
// ============================================================================= // =============================================================================
zmq_listener::zmq_listener(std::string _ip, uint32_t _zmq) : zmq_listener::zmq_listener(std::string _ip, uint32_t _zmq) :
@ -338,7 +384,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>(); rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>();
rpc_user = options.at("bitcoin-node-rpc-user").as<std::string>(); rpc_user = options.at("bitcoin-node-rpc-user").as<std::string>();
rpc_password = options.at("bitcoin-node-rpc-password").as<std::string>(); rpc_password = options.at("bitcoin-node-rpc-password").as<std::string>();
wallet = ""; std::string wallet = "";
if (options.count("bitcoin-wallet")) { if (options.count("bitcoin-wallet")) {
wallet = options.at("bitcoin-wallet").as<std::string>(); wallet = options.at("bitcoin-wallet").as<std::string>();
} }
@ -365,6 +411,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
} }
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls)); bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls));
lib_bitcoin_client = std::unique_ptr<bitcoin_libbitcoin_client>(new bitcoin_libbitcoin_client());
if (!wallet.empty()) { if (!wallet.empty()) {
bitcoin_client->loadwallet(wallet); bitcoin_client->loadwallet(wallet);
} }
@ -421,7 +468,7 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
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(sidechain))); // ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id(sidechain)));
bool should_approve = false; bool should_approve = false;
@ -1062,6 +1109,7 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
uint64_t total_amount = 0.0; uint64_t total_amount = 0.0;
std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(prev_pw_address, 0); std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(prev_pw_address, 0);
inputs = lib_bitcoin_client->listunspent_by_address_and_amount(prev_pw_address, 0);
if (inputs.size() == 0) { if (inputs.size() == 0) {
elog("Failed to find UTXOs to spend for ${pw}", ("pw", prev_pw_address)); elog("Failed to find UTXOs to spend for ${pw}", ("pw", prev_pw_address));
@ -1152,6 +1200,7 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s
int64_t total_amount = 0; int64_t total_amount = 0;
std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0); std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0);
inputs = lib_bitcoin_client->listunspent_by_address_and_amount(pw_address, 0);
if (inputs.size() == 0) { if (inputs.size() == 0) {
elog("Failed to find UTXOs to spend for ${pw}", ("pw", pw_address)); elog("Failed to find UTXOs to spend for ${pw}", ("pw", pw_address));
@ -1444,7 +1493,7 @@ void sidechain_net_handler_bitcoin::on_changed_objects_cb(const vector<object_id
} }
//! importmulti //! importmulti
bitcoin_client->importmulti(address_or_script_array); // bitcoin_client->importmulti(address_or_script_array);
//! Lock wallet //! Lock wallet
bitcoin_client->walletlock(); bitcoin_client->walletlock();