提交 cbac9107 编写于 作者: M Matt Witherspoon

Add HTTPS support (in addition to HTTP) for cleos

Add HTTPS support for cleos when talking to nodeos and keosd. This removes the -H, -P, and --wallet-* options in favor of options that specify the server as an entire URL such as https://server:8888/
上级 fe6961f7
...@@ -12,7 +12,9 @@ ...@@ -12,7 +12,9 @@
#include <istream> #include <istream>
#include <ostream> #include <ostream>
#include <string> #include <string>
#include <regex>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <fc/variant.hpp> #include <fc/variant.hpp>
#include <fc/io/json.hpp> #include <fc/io/json.hpp>
#include <eosio/chain/exceptions.hpp> #include <eosio/chain/exceptions.hpp>
...@@ -22,132 +24,155 @@ ...@@ -22,132 +24,155 @@
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
namespace eosio { namespace client { namespace http { namespace eosio { namespace client { namespace http {
fc::variant call( const std::string& server, uint16_t port, void do_connect(tcp::socket& sock, const std::string& server, const std::string& port) {
const std::string& path, // Get a list of endpoints corresponding to the server name.
const fc::variant& postdata ) { tcp::resolver resolver(sock.get_io_service());
try { tcp::resolver::query query(server, port);
std::string postjson; boost::asio::connect(sock, resolver.resolve(query));
if( !postdata.is_null() ) }
postjson = fc::json::to_string( postdata );
boost::asio::io_service io_service; template<class T>
std::string do_txrx(T& socket, boost::asio::streambuf& request_buff, unsigned int& status_code) {
// Send the request.
boost::asio::write(socket, request_buff);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
FC_ASSERT( !(!response_stream || http_version.substr(0, 5) != "HTTP/"), "Invalid Response" );
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
std::string header;
int response_content_length = -1;
std::regex clregex(R"xx(^content-length:\s+(\d+))xx", std::regex_constants::icase);
while (std::getline(response_stream, header) && header != "\r") {
std::smatch match;
if(std::regex_search(header, match, clregex))
response_content_length = std::stoi(match[1]);
}
FC_ASSERT(response_content_length >= 0, "Invalid content-length response");
// Get a list of endpoints corresponding to the server name. std::stringstream re;
tcp::resolver resolver(io_service); // Write whatever content we already have to output.
tcp::resolver::query query(server, std::to_string(port) ); response_content_length -= response.size();
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); if (response.size() > 0)
tcp::resolver::iterator end; re << &response;
while( endpoint_iterator != end ) { boost::asio::read(socket, response, boost::asio::transfer_exactly(response_content_length));
// Try each endpoint until we successfully establish a connection. re << &response;
tcp::socket socket(io_service);
try { return re.str();
boost::asio::connect(socket, endpoint_iterator); }
endpoint_iterator = end;
} catch( std::exception& e ) { fc::variant call( const std::string& server_url,
++endpoint_iterator; const std::string& path,
if( endpoint_iterator != end ) { const fc::variant& postdata ) {
continue; std::string postjson;
} else { if( !postdata.is_null() )
throw connection_exception(fc::log_messages{ postjson = fc::json::to_string( postdata );
FC_LOG_MESSAGE( error, "Connection to ${server}:${port}${path} is refused",
("server", server)("port", port)("path", path) ), boost::asio::io_service io_service;
FC_LOG_MESSAGE( error, e.what())
}); string scheme, server, port, path_prefix;
}
} //via rfc3986 and modified a bit to suck out the port number
//Sadly this doesn't work for ipv6 addresses
// Form the request. We specify the "Connection: close" header so that the std::regex rgx(R"xx(^(([^:/?#]+):)?(//([^:/?#]*)(:(\d+))?)?([^?#]*)(\?([^#]*))?(#(.*))?)xx");
// server will close the socket after transmitting the response. This will std::smatch match;
// allow us to treat all data up until the EOF as the content. if(std::regex_search(server_url.begin(), server_url.end(), match, rgx)) {
boost::asio::streambuf request; scheme = match[2];
std::ostream request_stream(&request); server = match[4];
request_stream << "POST " << path << " HTTP/1.0\r\n"; port = match[6];
request_stream << "Host: " << server << "\r\n"; path_prefix = match[7];
request_stream << "content-length: " << postjson.size() << "\r\n"; }
request_stream << "Accept: */*\r\n"; if(scheme != "http" && scheme != "https")
request_stream << "Connection: close\r\n\r\n"; FC_THROW("Unreconized URL scheme (${s}) in URL \"${u}\"", ("s", scheme)("u", server_url));
request_stream << postjson; if(server.empty())
FC_THROW("No server parsed from URL \"${u}\"", ("u", server_url));
// Send the request. if(port.empty())
boost::asio::write(socket, request); port = scheme == "http" ? "8888" : "443";
boost::trim_right_if(path_prefix, boost::is_any_of("/"));
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing boost::asio::streambuf request;
// a maximum size to the streambuf constructor. std::ostream request_stream(&request);
boost::asio::streambuf response; request_stream << "POST " << path_prefix + path << " HTTP/1.0\r\n";
boost::asio::read_until(socket, response, "\r\n"); request_stream << "Host: " << server << "\r\n";
request_stream << "content-length: " << postjson.size() << "\r\n";
// Check that response is OK. request_stream << "Accept: */*\r\n";
std::istream response_stream(&response); request_stream << "Connection: close\r\n\r\n";
std::string http_version; request_stream << postjson;
response_stream >> http_version;
unsigned int status_code; unsigned int status_code;
response_stream >> status_code; std::string re;
std::string status_message;
std::getline(response_stream, status_message); if(scheme == "http") {
FC_ASSERT( !(!response_stream || http_version.substr(0, 5) != "HTTP/"), "Invalid Response" ); tcp::socket socket(io_service);
do_connect(socket, server, port);
// Read the response headers, which are terminated by a blank line. re = do_txrx(socket, request, status_code);
boost::asio::read_until(socket, response, "\r\n\r\n"); }
else { //https
// Process the response headers. boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23_client);
std::string header; #if defined( __APPLE__ )
while (std::getline(response_stream, header) && header != "\r") //TODO: this is undocumented/not supported; fix with keychain based approach
{ ssl_context.load_verify_file("/private/etc/ssl/cert.pem");
// std::cout << header << "\n"; #elif defined( _WIN32 )
} FC_THROW("HTTPS on Windows not supported");
// std::cout << "\n"; #else
ssl_context.set_default_verify_paths();
std::stringstream re; #endif
// Write whatever content we already have to output.
if (response.size() > 0) boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service, ssl_context);
// std::cout << &response; socket.set_verify_mode(boost::asio::ssl::verify_peer);
re << &response;
do_connect(socket.next_layer(), server, port);
// Read until EOF, writing data to output as we go. socket.handshake(boost::asio::ssl::stream_base::client);
boost::system::error_code error; re = do_txrx(socket, request, status_code);
while (boost::asio::read(socket, response, //try and do a clean shutdown; but swallow if this fails (other side could have already gave TCP the ax)
boost::asio::transfer_at_least(1), error)) try {socket.shutdown();} catch(...) {}
re << &response; }
if (error != boost::asio::error::eof) const auto response_result = fc::json::from_string(re);
throw boost::system::system_error(error); if( status_code == 200 || status_code == 201 || status_code == 202 ) {
return response_result;
// std::cout << re.str() <<"\n"; } else if( status_code == 404 ) {
const auto response_result = fc::json::from_string(re.str()); // Unknown endpoint
if( status_code == 200 || status_code == 201 || status_code == 202 ) { if (path.compare(0, chain_func_base.size(), chain_func_base) == 0) {
return response_result; throw chain::missing_chain_api_plugin_exception(FC_LOG_MESSAGE(error, "Chain API plugin is not enabled"));
} else if( status_code == 404 ) { } else if (path.compare(0, wallet_func_base.size(), wallet_func_base) == 0) {
// Unknown endpoint throw chain::missing_wallet_api_plugin_exception(FC_LOG_MESSAGE(error, "Wallet is not available"));
if (path.compare(0, chain_func_base.size(), chain_func_base) == 0) { } else if (path.compare(0, account_history_func_base.size(), account_history_func_base) == 0) {
throw chain::missing_chain_api_plugin_exception(FC_LOG_MESSAGE(error, "Chain API plugin is not enabled")); throw chain::missing_account_history_api_plugin_exception(FC_LOG_MESSAGE(error, "Account History API plugin is not enabled"));
} else if (path.compare(0, wallet_func_base.size(), wallet_func_base) == 0) { } else if (path.compare(0, net_func_base.size(), net_func_base) == 0) {
throw chain::missing_wallet_api_plugin_exception(FC_LOG_MESSAGE(error, "Wallet is not available")); throw chain::missing_net_api_plugin_exception(FC_LOG_MESSAGE(error, "Net API plugin is not enabled"));
} else if (path.compare(0, account_history_func_base.size(), account_history_func_base) == 0) { }
throw chain::missing_account_history_api_plugin_exception(FC_LOG_MESSAGE(error, "Account History API plugin is not enabled")); } else {
} else if (path.compare(0, net_func_base.size(), net_func_base) == 0) { auto &&error_info = response_result.as<eosio::error_results>().error;
throw chain::missing_net_api_plugin_exception(FC_LOG_MESSAGE(error, "Net API plugin is not enabled")); // Construct fc exception from error
} const auto &error_details = error_info.details;
} else {
auto &&error_info = response_result.as<eosio::error_results>().error; fc::log_messages logs;
// Construct fc exception from error for (auto itr = error_details.begin(); itr != error_details.end(); itr++) {
const auto &error_details = error_info.details; const auto& context = fc::log_context(fc::log_level::error, itr->file.data(), itr->line_number, itr->method.data());
logs.emplace_back(fc::log_message(context, itr->message));
fc::log_messages logs;
for (auto itr = error_details.begin(); itr != error_details.end(); itr++) {
const auto& context = fc::log_context(fc::log_level::error, itr->file.data(), itr->line_number, itr->method.data());
logs.emplace_back(fc::log_message(context, itr->message));
}
throw fc::exception(logs, error_info.code, error_info.name, error_info.what);
}
FC_ASSERT( status_code == 200, "Error code ${c}\n: ${msg}\n", ("c", status_code)("msg", re.str()) );
} }
FC_ASSERT( !"unable to connect" ); throw fc::exception(logs, error_info.code, error_info.name, error_info.what);
} FC_CAPTURE_AND_RETHROW() // error, "Request Path: ${server}:${port}${path}\nRequest Post Data: ${postdata}" , }
// ("server", server)("port", port)("path", path)("postdata", postdata) )
FC_ASSERT( status_code == 200, "Error code ${c}\n: ${msg}\n", ("c", status_code)("msg", re) );
return response_result;
} }
}}} }}}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#pragma once #pragma once
namespace eosio { namespace client { namespace http { namespace eosio { namespace client { namespace http {
fc::variant call( const std::string& server, uint16_t port, fc::variant call( const std::string& server_url,
const std::string& path, const std::string& path,
const fc::variant& postdata = fc::variant() ); const fc::variant& postdata = fc::variant() );
......
...@@ -22,11 +22,10 @@ Usage: programs/cleos/cleos [OPTIONS] SUBCOMMAND ...@@ -22,11 +22,10 @@ Usage: programs/cleos/cleos [OPTIONS] SUBCOMMAND
Options: Options:
-h,--help Print this help message and exit -h,--help Print this help message and exit
-H,--host TEXT=localhost the host where nodeos is running -u,--url TEXT=http://localhost:8888/
-p,--port UINT=8888 the port where nodeos is running the http/https URL where nodeos is running
--wallet-host TEXT=localhost --wallet-url TEXT=http://localhost:8888/
the host where keosd is running the http/https URL where keosd is running
--wallet-port UINT=8888 the port where keosd is running
-v,--verbose output verbose actions on error -v,--verbose output verbose actions on error
Subcommands: Subcommands:
...@@ -39,7 +38,8 @@ Subcommands: ...@@ -39,7 +38,8 @@ Subcommands:
wallet Interact with local wallet wallet Interact with local wallet
sign Sign a transaction sign Sign a transaction
push Push arbitrary transactions to the blockchain push Push arbitrary transactions to the blockchain
multisig Multisig contract commands
``` ```
To get help with any particular subcommand, run it with no arguments as well: To get help with any particular subcommand, run it with no arguments as well:
``` ```
...@@ -134,13 +134,8 @@ FC_DECLARE_EXCEPTION( localized_exception, 10000000, "an error occured" ); ...@@ -134,13 +134,8 @@ FC_DECLARE_EXCEPTION( localized_exception, 10000000, "an error occured" );
FC_MULTILINE_MACRO_END \ FC_MULTILINE_MACRO_END \
) )
string program = "eosc"; string url = "http://localhost:8888/";
string host = "localhost"; string wallet_url = "http://localhost:8888/";
uint32_t port = 8888;
// restricting use of wallet to localhost
string wallet_host = "localhost";
uint32_t wallet_port = 8888;
auto tx_expiration = fc::seconds(30); auto tx_expiration = fc::seconds(30);
string tx_ref_block_num_or_id; string tx_ref_block_num_or_id;
...@@ -194,16 +189,27 @@ vector<chain::permission_level> get_account_permissions(const vector<string>& pe ...@@ -194,16 +189,27 @@ vector<chain::permission_level> get_account_permissions(const vector<string>& pe
} }
template<typename T> template<typename T>
fc::variant call( const std::string& server, uint16_t port, fc::variant call( const std::string& url,
const std::string& path, const std::string& path,
const T& v ) { return eosio::client::http::call( server, port, path, fc::variant(v) ); } const T& v ) {
try {
return eosio::client::http::call( url, path, fc::variant(v) );
}
catch(boost::system::system_error& e) {
if(url == ::url)
std::cerr << localized("Failed to connect to nodeos at ${u}; is nodeos running?", ("u", url)) << std::endl;
else if(url == ::wallet_url)
std::cerr << localized("Failed to connect to keosd at ${u}; is keosd running?", ("u", url)) << std::endl;
throw connection_exception(fc::log_messages{FC_LOG_MESSAGE(error, e.what())});
}
}
template<typename T> template<typename T>
fc::variant call( const std::string& path, fc::variant call( const std::string& path,
const T& v ) { return eosio::client::http::call( host, port, path, fc::variant(v) ); } const T& v ) { return ::call( url, path, fc::variant(v) ); }
eosio::chain_apis::read_only::get_info_results get_info() { eosio::chain_apis::read_only::get_info_results get_info() {
return call(host, port, get_info_func ).as<eosio::chain_apis::read_only::get_info_results>(); return ::call(url, get_info_func, fc::variant()).as<eosio::chain_apis::read_only::get_info_results>();
} }
string generate_nonce_value() { string generate_nonce_value() {
...@@ -228,18 +234,18 @@ chain::action generate_nonce() { ...@@ -228,18 +234,18 @@ chain::action generate_nonce() {
fc::variant determine_required_keys(const signed_transaction& trx) { fc::variant determine_required_keys(const signed_transaction& trx) {
// TODO better error checking // TODO better error checking
//wdump((trx)); //wdump((trx));
const auto& public_keys = call(wallet_host, wallet_port, wallet_public_keys); const auto& public_keys = call(wallet_url, wallet_public_keys);
auto get_arg = fc::mutable_variant_object auto get_arg = fc::mutable_variant_object
("transaction", (transaction)trx) ("transaction", (transaction)trx)
("available_keys", public_keys); ("available_keys", public_keys);
const auto& required_keys = call(host, port, get_required_keys, get_arg); const auto& required_keys = call(get_required_keys, get_arg);
return required_keys["required_keys"]; return required_keys["required_keys"];
} }
void sign_transaction(signed_transaction& trx, fc::variant& required_keys) { void sign_transaction(signed_transaction& trx, fc::variant& required_keys) {
// TODO determine chain id // TODO determine chain id
fc::variants sign_args = {fc::variant(trx), required_keys, fc::variant(chain_id_type{})}; fc::variants sign_args = {fc::variant(trx), required_keys, fc::variant(chain_id_type{})};
const auto& signed_trx = call(wallet_host, wallet_port, wallet_sign_trx, sign_args); const auto& signed_trx = call(wallet_url, wallet_sign_trx, sign_args);
trx = signed_trx.as<signed_transaction>(); trx = signed_trx.as<signed_transaction>();
} }
...@@ -528,6 +534,13 @@ struct set_action_permission_subcommand { ...@@ -528,6 +534,13 @@ struct set_action_permission_subcommand {
} }
}; };
CLI::callback_t old_host_port = [](CLI::results_t) {
std::cerr << localized("Host and port options (-H, --wallet-host, etc.) have been replaced with -u/--url and --wallet-url\n"
"Use for example -u http://localhost:8888 or --url https://example.invalid/\n");
exit(1);
return false;
};
int main( int argc, char** argv ) { int main( int argc, char** argv ) {
fc::path binPath = argv[0]; fc::path binPath = argv[0];
if (binPath.is_relative()) { if (binPath.is_relative()) {
...@@ -540,10 +553,13 @@ int main( int argc, char** argv ) { ...@@ -540,10 +553,13 @@ int main( int argc, char** argv ) {
CLI::App app{"Command Line Interface to EOSIO Client"}; CLI::App app{"Command Line Interface to EOSIO Client"};
app.require_subcommand(); app.require_subcommand();
app.add_option( "-H,--host", host, localized("the host where nodeos is running"), true ); app.add_option( "-H,--host", old_host_port, localized("the host where nodeos is running") )->group("hidden");
app.add_option( "-p,--port", port, localized("the port where nodeos is running"), true ); app.add_option( "-p,--port", old_host_port, localized("the port where nodeos is running") )->group("hidden");
app.add_option( "--wallet-host", wallet_host, localized("the host where keosd is running"), true ); app.add_option( "--wallet-host", old_host_port, localized("the host where keosd is running") )->group("hidden");
app.add_option( "--wallet-port", wallet_port, localized("the port where keosd is running"), true ); app.add_option( "--wallet-port", old_host_port, localized("the port where keosd is running") )->group("hidden");
app.add_option( "-u,--url", url, localized("the http/https URL where nodeos is running"), true );
app.add_option( "--wallet-url", wallet_url, localized("the http/https URL where keosd is running"), true );
bool verbose_errors = false; bool verbose_errors = false;
app.add_flag( "-v,--verbose", verbose_errors, localized("output verbose actions on error")); app.add_flag( "-v,--verbose", verbose_errors, localized("output verbose actions on error"));
...@@ -923,27 +939,27 @@ int main( int argc, char** argv ) { ...@@ -923,27 +939,27 @@ int main( int argc, char** argv ) {
auto connect = net->add_subcommand("connect", localized("start a new connection to a peer"), false); auto connect = net->add_subcommand("connect", localized("start a new connection to a peer"), false);
connect->add_option("host", new_host, localized("The hostname:port to connect to."))->required(); connect->add_option("host", new_host, localized("The hostname:port to connect to."))->required();
connect->set_callback([&] { connect->set_callback([&] {
const auto& v = call(host, port, net_connect, new_host); const auto& v = call(net_connect, new_host);
std::cout << fc::json::to_pretty_string(v) << std::endl; std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
auto disconnect = net->add_subcommand("disconnect", localized("close an existing connection"), false); auto disconnect = net->add_subcommand("disconnect", localized("close an existing connection"), false);
disconnect->add_option("host", new_host, localized("The hostname:port to disconnect from."))->required(); disconnect->add_option("host", new_host, localized("The hostname:port to disconnect from."))->required();
disconnect->set_callback([&] { disconnect->set_callback([&] {
const auto& v = call(host, port, net_disconnect, new_host); const auto& v = call(net_disconnect, new_host);
std::cout << fc::json::to_pretty_string(v) << std::endl; std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
auto status = net->add_subcommand("status", localized("status of existing connection"), false); auto status = net->add_subcommand("status", localized("status of existing connection"), false);
status->add_option("host", new_host, localized("The hostname:port to query status of connection"))->required(); status->add_option("host", new_host, localized("The hostname:port to query status of connection"))->required();
status->set_callback([&] { status->set_callback([&] {
const auto& v = call(host, port, net_status, new_host); const auto& v = call(net_status, new_host);
std::cout << fc::json::to_pretty_string(v) << std::endl; std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
auto connections = net->add_subcommand("peers", localized("status of all existing peers"), false); auto connections = net->add_subcommand("peers", localized("status of all existing peers"), false);
connections->set_callback([&] { connections->set_callback([&] {
const auto& v = call(host, port, net_connections, new_host); const auto& v = call(net_connections, new_host);
std::cout << fc::json::to_pretty_string(v) << std::endl; std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
...@@ -957,7 +973,7 @@ int main( int argc, char** argv ) { ...@@ -957,7 +973,7 @@ int main( int argc, char** argv ) {
auto createWallet = wallet->add_subcommand("create", localized("Create a new wallet locally"), false); auto createWallet = wallet->add_subcommand("create", localized("Create a new wallet locally"), false);
createWallet->add_option("-n,--name", wallet_name, localized("The name of the new wallet"), true); createWallet->add_option("-n,--name", wallet_name, localized("The name of the new wallet"), true);
createWallet->set_callback([&wallet_name] { createWallet->set_callback([&wallet_name] {
const auto& v = call(wallet_host, wallet_port, wallet_create, wallet_name); const auto& v = call(wallet_url, wallet_create, wallet_name);
std::cout << localized("Creating wallet: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl; std::cout << localized("Creating wallet: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl;
std::cout << localized("Save password to use in the future to unlock this wallet.") << std::endl; std::cout << localized("Save password to use in the future to unlock this wallet.") << std::endl;
std::cout << localized("Without password imported keys will not be retrievable.") << std::endl; std::cout << localized("Without password imported keys will not be retrievable.") << std::endl;
...@@ -968,8 +984,7 @@ int main( int argc, char** argv ) { ...@@ -968,8 +984,7 @@ int main( int argc, char** argv ) {
auto openWallet = wallet->add_subcommand("open", localized("Open an existing wallet"), false); auto openWallet = wallet->add_subcommand("open", localized("Open an existing wallet"), false);
openWallet->add_option("-n,--name", wallet_name, localized("The name of the wallet to open")); openWallet->add_option("-n,--name", wallet_name, localized("The name of the wallet to open"));
openWallet->set_callback([&wallet_name] { openWallet->set_callback([&wallet_name] {
/*const auto& v = */call(wallet_host, wallet_port, wallet_open, wallet_name); call(wallet_url, wallet_open, wallet_name);
//std::cout << fc::json::to_pretty_string(v) << std::endl;
std::cout << localized("Opened: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl; std::cout << localized("Opened: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl;
}); });
...@@ -977,17 +992,14 @@ int main( int argc, char** argv ) { ...@@ -977,17 +992,14 @@ int main( int argc, char** argv ) {
auto lockWallet = wallet->add_subcommand("lock", localized("Lock wallet"), false); auto lockWallet = wallet->add_subcommand("lock", localized("Lock wallet"), false);
lockWallet->add_option("-n,--name", wallet_name, localized("The name of the wallet to lock")); lockWallet->add_option("-n,--name", wallet_name, localized("The name of the wallet to lock"));
lockWallet->set_callback([&wallet_name] { lockWallet->set_callback([&wallet_name] {
/*const auto& v = */call(wallet_host, wallet_port, wallet_lock, wallet_name); call(wallet_url, wallet_lock, wallet_name);
std::cout << localized("Locked: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl; std::cout << localized("Locked: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl;
//std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
// lock all wallets // lock all wallets
auto locakAllWallets = wallet->add_subcommand("lock_all", localized("Lock all unlocked wallets"), false); auto locakAllWallets = wallet->add_subcommand("lock_all", localized("Lock all unlocked wallets"), false);
locakAllWallets->set_callback([] { locakAllWallets->set_callback([] {
/*const auto& v = */call(wallet_host, wallet_port, wallet_lock_all); call(wallet_url, wallet_lock_all);
//std::cout << fc::json::to_pretty_string(v) << std::endl;
std::cout << localized("Locked All Wallets") << std::endl; std::cout << localized("Locked All Wallets") << std::endl;
}); });
...@@ -1006,9 +1018,8 @@ int main( int argc, char** argv ) { ...@@ -1006,9 +1018,8 @@ int main( int argc, char** argv ) {
fc::variants vs = {fc::variant(wallet_name), fc::variant(wallet_pw)}; fc::variants vs = {fc::variant(wallet_name), fc::variant(wallet_pw)};
/*const auto& v = */call(wallet_host, wallet_port, wallet_unlock, vs); call(wallet_url, wallet_unlock, vs);
std::cout << localized("Unlocked: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl; std::cout << localized("Unlocked: ${wallet_name}", ("wallet_name", wallet_name)) << std::endl;
//std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
// import keys into wallet // import keys into wallet
...@@ -1026,23 +1037,22 @@ int main( int argc, char** argv ) { ...@@ -1026,23 +1037,22 @@ int main( int argc, char** argv ) {
public_key_type pubkey = wallet_key.get_public_key(); public_key_type pubkey = wallet_key.get_public_key();
fc::variants vs = {fc::variant(wallet_name), fc::variant(wallet_key)}; fc::variants vs = {fc::variant(wallet_name), fc::variant(wallet_key)};
const auto& v = call(wallet_host, wallet_port, wallet_import_key, vs); call(wallet_url, wallet_import_key, vs);
std::cout << localized("imported private key for: ${pubkey}", ("pubkey", std::string(pubkey))) << std::endl; std::cout << localized("imported private key for: ${pubkey}", ("pubkey", std::string(pubkey))) << std::endl;
//std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
// list wallets // list wallets
auto listWallet = wallet->add_subcommand("list", localized("List opened wallets, * = unlocked"), false); auto listWallet = wallet->add_subcommand("list", localized("List opened wallets, * = unlocked"), false);
listWallet->set_callback([] { listWallet->set_callback([] {
std::cout << localized("Wallets:") << std::endl; std::cout << localized("Wallets:") << std::endl;
const auto& v = call(wallet_host, wallet_port, wallet_list); const auto& v = call(wallet_url, wallet_list);
std::cout << fc::json::to_pretty_string(v) << std::endl; std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
// list keys // list keys
auto listKeys = wallet->add_subcommand("keys", localized("List of private keys from all unlocked wallets in wif format."), false); auto listKeys = wallet->add_subcommand("keys", localized("List of private keys from all unlocked wallets in wif format."), false);
listKeys->set_callback([] { listKeys->set_callback([] {
const auto& v = call(wallet_host, wallet_port, wallet_list_keys); const auto& v = call(wallet_url, wallet_list_keys);
std::cout << fc::json::to_pretty_string(v) << std::endl; std::cout << fc::json::to_pretty_string(v) << std::endl;
}); });
...@@ -1415,18 +1425,9 @@ int main( int argc, char** argv ) { ...@@ -1415,18 +1425,9 @@ int main( int argc, char** argv ) {
} catch (const explained_exception& e) { } catch (const explained_exception& e) {
return 1; return 1;
} catch (connection_exception& e) { } catch (connection_exception& e) {
auto errorString = e.to_detail_string(); if (verbose_errors) {
if (errorString.find(fc::json::to_string(port)) != string::npos) { elog("connect error: ${e}", ("e", e.to_detail_string()));
std::cerr << localized("Failed to connect to nodeos at ${ip}:${port}; is nodeos running?", ("ip", host)("port", port)) << std::endl; }
} else if (errorString.find(fc::json::to_string(wallet_port)) != string::npos) {
std::cerr << localized("Failed to connect to keosd at ${ip}:${port}; is keosd running?", ("ip", wallet_host)("port", wallet_port)) << std::endl;
} else {
std::cerr << localized("Failed to connect") << std::endl;
}
if (verbose_errors) {
elog("connect error: ${e}", ("e", errorString));
}
} catch (const fc::exception& e) { } catch (const fc::exception& e) {
// attempt to extract the error code if one is present // attempt to extract the error code if one is present
if (!print_recognized_errors(e, verbose_errors)) { if (!print_recognized_errors(e, verbose_errors)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册