Add loading/unlocking/locking of non-default bitcoin wallet

This commit is contained in:
Srdjan Obucina 2020-02-29 18:30:00 +01:00
parent da0b3fafd2
commit 57a9675282
3 changed files with 47 additions and 36 deletions

View file

@ -39,7 +39,7 @@ public:
std::string signrawtransactionwithwallet(const std::string &tx_hash); std::string signrawtransactionwithwallet(const std::string &tx_hash);
std::string unloadwallet(const std::string &filename); std::string unloadwallet(const std::string &filename);
std::string walletlock(); std::string walletlock();
std::string walletpassphrase(const std::string &passphrase, uint32_t timeout = 60); std::string walletpassphrase(const std::string &passphrase, uint32_t timeout = 5);
private: private:
fc::http::reply send_post_request(std::string body); fc::http::reply send_post_request(std::string body);
@ -96,8 +96,8 @@ private:
std::string wallet; std::string wallet;
std::string wallet_password; std::string wallet_password;
std::unique_ptr<zmq_listener> listener;
std::unique_ptr<bitcoin_rpc_client> bitcoin_client; std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
std::unique_ptr<zmq_listener> listener;
std::string create_multisignature_wallet(const std::vector<std::string> public_keys); std::string create_multisignature_wallet(const std::vector<std::string> public_keys);
std::string transfer(const std::string &from, const std::string &to, const uint64_t amount); std::string transfer(const std::string &from, const std::string &to, const uint64_t amount);

View file

@ -29,7 +29,7 @@ public:
void plugin_set_program_options( void plugin_set_program_options(
boost::program_options::options_description &cli, boost::program_options::options_description &cli,
boost::program_options::options_description &cfg); boost::program_options::options_description &cfg);
void plugin_initialize(const boost::program_options::variables_map &options); void plugin_initialize(const boost::program_options::variables_map &opt);
void plugin_startup(); void plugin_startup();
std::set<chain::son_id_type> &get_sons(); std::set<chain::son_id_type> &get_sons();
@ -53,6 +53,8 @@ public:
private: private:
peerplays_sidechain_plugin &plugin; peerplays_sidechain_plugin &plugin;
boost::program_options::variables_map options;
bool config_ready_son; bool config_ready_son;
bool config_ready_bitcoin; bool config_ready_bitcoin;
bool config_ready_peerplays; bool config_ready_peerplays;
@ -60,7 +62,7 @@ private:
son_id_type current_son_id; son_id_type current_son_id;
std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager; std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager;
std::set<chain::son_id_type> _sons; std::set<chain::son_id_type> sons;
std::map<chain::public_key_type, fc::ecc::private_key> private_keys; std::map<chain::public_key_type, fc::ecc::private_key> private_keys;
fc::future<void> _heartbeat_task; fc::future<void> _heartbeat_task;
fc::future<void> _son_processing_task; fc::future<void> _son_processing_task;
@ -120,16 +122,17 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
cfg.add(cli); cfg.add(cli);
} }
void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_options::variables_map &options) { void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_options::variables_map &opt) {
options = opt;
config_ready_son = (options.count("son-id") || options.count("son-ids")) && options.count("peerplays-private-key"); config_ready_son = (options.count("son-id") || options.count("son-ids")) && options.count("peerplays-private-key");
if (config_ready_son) { if (config_ready_son) {
LOAD_VALUE_SET(options, "son-id", _sons, chain::son_id_type) LOAD_VALUE_SET(options, "son-id", sons, chain::son_id_type)
if (options.count("son-ids")) if (options.count("son-ids"))
boost::insert(_sons, fc::json::from_string(options.at("son-ids").as<string>()).as<vector<chain::son_id_type>>(5)); boost::insert(sons, fc::json::from_string(options.at("son-ids").as<string>()).as<vector<chain::son_id_type>>(5));
config_ready_son = config_ready_son && !_sons.empty(); config_ready_son = config_ready_son && !sons.empty();
#ifndef SUPPORT_MULTIPLE_SONS #ifndef SUPPORT_MULTIPLE_SONS
FC_ASSERT(_sons.size() == 1, "Multiple SONs not supported"); FC_ASSERT(sons.size() == 1, "Multiple SONs not supported");
#endif #endif
if (options.count("peerplays-private-key")) { if (options.count("peerplays-private-key")) {
@ -149,77 +152,74 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
} }
private_keys[key_id_to_wif_pair.first] = *private_key; private_keys[key_id_to_wif_pair.first] = *private_key;
} }
config_ready_son = config_ready_son && !private_keys.empty();
} }
} else { }
if (!config_ready_son) {
wlog("Haven't set up SON parameters"); wlog("Haven't set up SON parameters");
throw; throw;
} }
plugin.database().applied_block.connect([&](const signed_block &b) {
on_applied_block(b);
});
net_manager = std::unique_ptr<sidechain_net_manager>(new sidechain_net_manager(plugin));
config_ready_bitcoin = options.count("bitcoin-node-ip") && config_ready_bitcoin = options.count("bitcoin-node-ip") &&
options.count("bitcoin-node-zmq-port") && options.count("bitcoin-node-rpc-port") && options.count("bitcoin-node-zmq-port") && options.count("bitcoin-node-rpc-port") &&
options.count("bitcoin-node-rpc-user") && options.count("bitcoin-node-rpc-password") && options.count("bitcoin-node-rpc-user") && options.count("bitcoin-node-rpc-password") &&
/*options.count( "bitcoin-wallet" ) && options.count( "bitcoin-wallet-password" ) &&*/ /*options.count( "bitcoin-wallet" ) && options.count( "bitcoin-wallet-password" ) &&*/
options.count("bitcoin-private-key"); options.count("bitcoin-private-key");
if (config_ready_bitcoin) { if (!config_ready_bitcoin) {
net_manager->create_handler(sidechain_type::bitcoin, options);
ilog("Bitcoin sidechain handler created");
} else {
wlog("Haven't set up Bitcoin sidechain parameters"); wlog("Haven't set up Bitcoin sidechain parameters");
} }
//config_ready_ethereum = options.count( "ethereum-node-ip" ) && //config_ready_ethereum = options.count( "ethereum-node-ip" ) &&
// options.count( "ethereum-address" ) && options.count( "ethereum-public-key" ) && options.count( "ethereum-private-key" ); // options.count( "ethereum-address" ) && options.count( "ethereum-public-key" ) && options.count( "ethereum-private-key" );
//if (config_ready_ethereum) { //if (!config_ready_ethereum) {
// net_manager->create_handler(sidechain_type::ethereum, options);
// ilog("Ethereum sidechain handler created");
//} else {
// wlog("Haven't set up Ethereum sidechain parameters"); // wlog("Haven't set up Ethereum sidechain parameters");
//} //}
config_ready_peerplays = true; config_ready_peerplays = true;
if (config_ready_peerplays) { if (!config_ready_peerplays) {
net_manager->create_handler(sidechain_type::peerplays, options);
ilog("Peerplays sidechain handler created");
} else {
wlog("Haven't set up Peerplays sidechain parameters"); wlog("Haven't set up Peerplays sidechain parameters");
} }
if (!(config_ready_bitcoin /*&& config_ready_ethereum*/)) { if (!(config_ready_bitcoin /*&& config_ready_ethereum*/ && config_ready_peerplays)) {
wlog("Haven't set up any sidechain parameters"); wlog("Haven't set up any sidechain parameters");
throw; throw;
} }
} }
void peerplays_sidechain_plugin_impl::plugin_startup() { void peerplays_sidechain_plugin_impl::plugin_startup() {
plugin.database().applied_block.connect([&](const signed_block &b) {
on_applied_block(b);
});
if (config_ready_son) { if (config_ready_son) {
ilog("Starting ${n} SON instances", ("n", _sons.size())); ilog("Starting ${n} SON instances", ("n", sons.size()));
schedule_heartbeat_loop(); schedule_heartbeat_loop();
} else { } else {
elog("No sons configured! Please add SON IDs and private keys to configuration."); elog("No sons configured! Please add SON IDs and private keys to configuration.");
} }
net_manager = std::unique_ptr<sidechain_net_manager>(new sidechain_net_manager(plugin));
if (config_ready_bitcoin) { if (config_ready_bitcoin) {
net_manager->create_handler(sidechain_type::bitcoin, options);
ilog("Bitcoin sidechain handler running"); ilog("Bitcoin sidechain handler running");
} }
//if (config_ready_ethereum) { //if (config_ready_ethereum) {
// net_manager->create_handler(sidechain_type::ethereum, options);
// ilog("Ethereum sidechain handler running"); // ilog("Ethereum sidechain handler running");
//} //}
if (config_ready_peerplays) { if (config_ready_peerplays) {
net_manager->create_handler(sidechain_type::peerplays, options);
ilog("Peerplays sidechain handler running"); ilog("Peerplays sidechain handler running");
} }
} }
std::set<chain::son_id_type> &peerplays_sidechain_plugin_impl::get_sons() { std::set<chain::son_id_type> &peerplays_sidechain_plugin_impl::get_sons() {
return _sons; return sons;
} }
son_id_type &peerplays_sidechain_plugin_impl::get_current_son_id() { son_id_type &peerplays_sidechain_plugin_impl::get_current_son_id() {
@ -282,7 +282,7 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() {
schedule_heartbeat_loop(); schedule_heartbeat_loop();
chain::database &d = plugin.database(); chain::database &d = plugin.database();
for (son_id_type son_id : _sons) { for (son_id_type son_id : sons) {
if (is_active_son(son_id) || get_son_object(son_id).status == chain::son_status::in_maintenance) { if (is_active_son(son_id) || get_son_object(son_id).status == chain::son_status::in_maintenance) {
ilog("peerplays_sidechain_plugin: sending heartbeat for SON ${son}", ("son", son_id)); ilog("peerplays_sidechain_plugin: sending heartbeat for SON ${son}", ("son", son_id));
@ -332,7 +332,7 @@ void peerplays_sidechain_plugin_impl::son_processing() {
approve_proposals(); approve_proposals();
// Tasks that are executed by scheduled and active SON // Tasks that are executed by scheduled and active SON
if (_sons.find(next_son_id) != _sons.end()) { if (sons.find(next_son_id) != sons.end()) {
current_son_id = next_son_id; current_son_id = next_son_id;
@ -373,7 +373,7 @@ void peerplays_sidechain_plugin_impl::approve_proposals() {
const auto &idx = plugin.database().get_index_type<proposal_index>().indices().get<by_id>(); const auto &idx = plugin.database().get_index_type<proposal_index>().indices().get<by_id>();
for (const auto &proposal : idx) { for (const auto &proposal : idx) {
for (son_id_type son_id : _sons) { for (son_id_type son_id : sons) {
if (!is_active_son(son_id)) { if (!is_active_son(son_id)) {
continue; continue;
} }

View file

@ -66,7 +66,7 @@ std::string bitcoin_rpc_client::addmultisigaddress(const std::vector<std::string
} }
if (json.count("error") && !json.get_child("error").empty()) { if (json.count("error") && !json.get_child("error").empty()) {
wlog("BTC multisig address creation failed! Reply: ${msg}", ("msg", ss.str())); wlog("Bitcoin RPC call ${function} failed with reply '${msg}'", ("function", __FUNCTION__)("msg", ss.str()));
} }
return ""; return "";
} }
@ -589,9 +589,12 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
FC_ASSERT(false); FC_ASSERT(false);
} }
listener = std::unique_ptr<zmq_listener>(new zmq_listener(ip, zmq_port));
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password)); bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password));
if (!wallet.empty()) {
bitcoin_client->loadwallet(wallet);
}
listener = std::unique_ptr<zmq_listener>(new zmq_listener(ip, zmq_port));
listener->event_received.connect([this](const std::string &event_data) { listener->event_received.connect([this](const std::string &event_data) {
std::thread(&sidechain_net_handler_bitcoin::handle_event, this, event_data).detach(); std::thread(&sidechain_net_handler_bitcoin::handle_event, this, event_data).detach();
}); });
@ -706,12 +709,20 @@ std::string sidechain_net_handler_bitcoin::sign_and_send_transaction_with_wallet
std::string unsigned_tx_hex = pt.get<std::string>("result"); std::string unsigned_tx_hex = pt.get<std::string>("result");
if (!wallet_password.empty()) {
bitcoin_client->walletpassphrase(wallet_password);
}
reply_str = bitcoin_client->signrawtransactionwithwallet(unsigned_tx_hex); reply_str = bitcoin_client->signrawtransactionwithwallet(unsigned_tx_hex);
ilog(reply_str); ilog(reply_str);
std::stringstream ss_stx(reply_str); std::stringstream ss_stx(reply_str);
boost::property_tree::ptree stx_json; boost::property_tree::ptree stx_json;
boost::property_tree::read_json(ss_stx, stx_json); boost::property_tree::read_json(ss_stx, stx_json);
//if (!wallet_password.empty()) {
// bitcoin_client->walletlock();
//}
if (!(stx_json.count("error") && stx_json.get_child("error").empty()) || !stx_json.count("result") || !stx_json.get_child("result").count("hex")) { if (!(stx_json.count("error") && stx_json.get_child("error").empty()) || !stx_json.count("result") || !stx_json.get_child("result").count("hex")) {
return ""; return "";
} }