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/utils.cpp
bitcoin/sign_bitcoin_transaction.cpp
bitcoin/libbitcoin_client.cpp
common/rpc_client.cpp
common/utils.cpp
hive/asset.cpp
@ -36,7 +37,7 @@ endif()
unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS)
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
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
#include <graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp>
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
@ -23,7 +24,7 @@ public:
uint64_t amount_;
};
class bitcoin_rpc_client : public rpc_client {
class bitcoin_client {
public:
enum class multi_type {
script,
@ -41,10 +42,20 @@ public:
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:
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);
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
std::string getrawtransaction(const std::string &txid, const bool verbose = false);
@ -60,13 +71,23 @@ public:
private:
std::string ip;
uint32_t rpc_port;
std::string user;
std::string password;
std::string wallet;
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 {
@ -118,6 +139,7 @@ private:
std::string wallet_password;
std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
std::unique_ptr<bitcoin_libbitcoin_client> lib_bitcoin_client;
std::unique_ptr<zmq_listener> listener;
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) {
}
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) {
std::string params = std::string("[") + std::to_string(conf_target) + std::string("]");
std::string str = send_post_request("estimatesmartfee", params, debug_rpc_calls);
@ -110,11 +104,11 @@ void bitcoin_rpc_client::importmulti(const std::vector<multi_params> &address_or
//! Note
/* Creation time of the key expressed in UNIX epoch time,
or the string "now" to substitute the current synced blockchain time. The timestamp of the oldest
key will determine how far back blockchain rescans need to begin for missing wallet transactions.
"now" can be specified to bypass scanning, for keys which are known to never have been used, and
0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key
creation time of all keys being imported by the importmulti call will be scanned.*/
or the string "now" to substitute the current synced blockchain time. The timestamp of the oldest
key will determine how far back blockchain rescans need to begin for missing wallet transactions.
"now" can be specified to bypass scanning, for keys which are known to never have been used, and
0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key
creation time of all keys being imported by the importmulti call will be scanned.*/
if (&param != &address_or_script_array.back()) {
argument_1 += ", ";
@ -251,6 +245,58 @@ bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_
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) :
@ -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_user = options.at("bitcoin-node-rpc-user").as<std::string>();
rpc_password = options.at("bitcoin-node-rpc-password").as<std::string>();
wallet = "";
std::string wallet = "";
if (options.count("bitcoin-wallet")) {
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));
lib_bitcoin_client = std::unique_ptr<bitcoin_libbitcoin_client>(new bitcoin_libbitcoin_client());
if (!wallet.empty()) {
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) {
//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;
@ -1062,6 +1109,7 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
uint64_t total_amount = 0.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) {
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;
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) {
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
bitcoin_client->importmulti(address_or_script_array);
// bitcoin_client->importmulti(address_or_script_array);
//! Lock wallet
bitcoin_client->walletlock();