diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt old mode 100755 new mode 100644 index d7337e42..326cff88 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -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" ) diff --git a/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp b/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp new file mode 100644 index 00000000..fc985fca --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/bitcoin/libbitcoin_client.cpp @@ -0,0 +1,87 @@ + +#include + +#include + +#include + +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"< libbitcoin_client::list_unspent(std::string address, double amount) { + std::vector 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 \ No newline at end of file diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp new file mode 100644 index 00000000..d0a1fa70 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/bitcoin/libbitcoin_client.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +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(std::string address, double amount); + +private: + libbitcoin::client::obelisk_client obelisk_client; +}; + +}} // namespace graphene::peerplays_sidechain \ No newline at end of file diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index 9a858cb7..7c5c854f 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -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 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 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_client; + std::unique_ptr lib_bitcoin_client; std::unique_ptr listener; fc::future on_changed_objects_task; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index fd3909bf..186ccdf9 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -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 &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 (¶m != &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 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 result; + std::vector 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(); rpc_user = options.at("bitcoin-node-rpc-user").as(); rpc_password = options.at("bitcoin-node-rpc-password").as(); - wallet = ""; + std::string wallet = ""; if (options.count("bitcoin-wallet")) { wallet = options.at("bitcoin-wallet").as(); } @@ -365,6 +411,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain } bitcoin_client = std::unique_ptr(new bitcoin_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls)); + lib_bitcoin_client = std::unique_ptr(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 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 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 vectorimportmulti(address_or_script_array); + // bitcoin_client->importmulti(address_or_script_array); //! Lock wallet bitcoin_client->walletlock();