diff --git a/plugins/wallet_api_plugin/include/eos/wallet_api_plugin/wallet_api_plugin.hpp b/plugins/wallet_api_plugin/include/eos/wallet_api_plugin/wallet_api_plugin.hpp index 91c3090342e9e537065972658b02bd0615e6ec85..56c6c2d36fff467cfbca7ecfa623508fed54d262 100644 --- a/plugins/wallet_api_plugin/include/eos/wallet_api_plugin/wallet_api_plugin.hpp +++ b/plugins/wallet_api_plugin/include/eos/wallet_api_plugin/wallet_api_plugin.hpp @@ -1,4 +1,5 @@ #pragma once + #include #include @@ -6,20 +7,25 @@ namespace eos { - using namespace appbase; +using namespace appbase; + +class wallet_api_plugin : public plugin { +public: + APPBASE_PLUGIN_REQUIRES((wallet_plugin) (http_plugin)) - class wallet_api_plugin : public plugin { - public: - APPBASE_PLUGIN_REQUIRES((wallet_plugin)(http_plugin)) + wallet_api_plugin() = default; + wallet_api_plugin(const wallet_api_plugin&) = delete; + wallet_api_plugin(wallet_api_plugin&&) = delete; + wallet_api_plugin& operator=(const wallet_api_plugin&) = delete; + wallet_api_plugin& operator=(wallet_api_plugin&&) = delete; + virtual ~wallet_api_plugin() override = default; - wallet_api_plugin() = default; - virtual ~wallet_api_plugin() = default; - virtual void set_program_options(options_description&, options_description&) override {} - void plugin_initialize(const variables_map&) {} - void plugin_startup(); - void plugin_shutdown() {} + virtual void set_program_options(options_description& cli, options_description& cfg) override {} + void plugin_initialize(const variables_map& vm) {} + void plugin_startup(); + void plugin_shutdown() {} - private: - }; +private: +}; } diff --git a/plugins/wallet_api_plugin/wallet_api_plugin.cpp b/plugins/wallet_api_plugin/wallet_api_plugin.cpp index 2099eb2be27379f4a0d5c4abe3cd57fed76ef29d..124baf1ce35b037a789c0e948bb900e055d0cded 100644 --- a/plugins/wallet_api_plugin/wallet_api_plugin.cpp +++ b/plugins/wallet_api_plugin/wallet_api_plugin.cpp @@ -37,6 +37,10 @@ using namespace eos; #define INVOKE_R_R(api_handle, call_name, in_param) \ auto result = api_handle.call_name(fc::json::from_string(body).as()); +#define INVOKE_R_R_R(api_handle, call_name, in_param0, in_param1) \ + const auto& vs = fc::json::json::from_string(body).as(); \ + auto result = api_handle.call_name(vs.at(0).as(), vs.at(1).as()); + #define INVOKE_R_V(api_handle, call_name) \ auto result = api_handle.call_name(); @@ -61,7 +65,7 @@ void wallet_api_plugin::plugin_startup() { app().get_plugin().add_api({ CALL(wallet, wallet_mgr, sign_transaction, - INVOKE_R_R(wallet_mgr, sign_transaction, chain::SignedTransaction)), + INVOKE_R_R_R(wallet_mgr, sign_transaction, chain::SignedTransaction, chain::chain_id_type)), CALL(wallet, wallet_mgr, create, INVOKE_R_R(wallet_mgr, create, std::string)), CALL(wallet, wallet_mgr, open, diff --git a/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_manager.hpp b/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_manager.hpp index 927c9480dd297e10b1994795359a3d77f7de35da..5933c8e3c08deb760491129e8aba9b0f537ba830 100644 --- a/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_manager.hpp +++ b/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_manager.hpp @@ -8,24 +8,73 @@ namespace fc { class variant; } namespace eos { namespace wallet { +/// Provides associate of wallet name to wallet and manages the interaction with each wallet. +/// +/// The name of the wallet is also used as part of the file name by wallet_api. See wallet_manager#create. class wallet_manager { public: wallet_manager() = default; wallet_manager(const wallet_manager&) = delete; wallet_manager(wallet_manager&&) = delete; + wallet_manager& operator=(const wallet_manager&) = delete; + wallet_manager& operator=(wallet_manager&&) = delete; ~wallet_manager() = default; + /// Set the path for location of wallet files. + /// @param p path to override default ./ location of wallet files. void set_dir(const boost::filesystem::path& p) { dir = p; } - chain::SignedTransaction sign_transaction(const chain::SignedTransaction& txn) const; + /// Sign transaction with all the keys from all the unlocked wallets. + /// @param txn the transaction to sign. + /// @param id the chain_id to sign transaction with. + /// @return txn signed + /// @throws fc::exception if no unlocked wallets + chain::SignedTransaction sign_transaction(const chain::SignedTransaction& txn, const chain::chain_id_type& id) const; + /// Create a new wallet. + /// A new wallet is created in file dir/{name}.wallet see wallet_manager#set_dir. + /// The new wallet is unlocked after creation. + /// @param name of the wallet and name of the file without ext .wallet. + /// @return Plaintext password that is needed to unlock wallet. Caller is responsible for saving password otherwise + /// they will not be able to unlock their wallet. Note user supplied passwords are not supported. + /// @throws fc::exception if wallet with name already exists (or filename already exists) std::string create(const std::string& name); + + /// Open an existing wallet file dir/{name}.wallet. + /// Note this does not unlock the wallet, see wallet_manager#unlock. + /// @param name of the wallet file (minus ext .wallet) to open. + /// @throws fc::exception if unable to find/open the wallet file. void open(const std::string& name); + + /// @return A list of wallet names with " *" appended if the wallet is unlocked. std::vector list_wallets() const; + + /// @return A list of unlocked wallet names and their private keys. + /// Wallet name entry followed by private key entries. std::vector list_keys() const; + + /// Locks all the unlocked wallets. void lock_all(); + + /// Lock the specified wallet. + /// No-op if wallet already locked. + /// @param name the name of the wallet to lock. + /// @throws fc::exception if wallet with name not found. void lock(const std::string& name); + + /// Unlock the specified wallet. + /// The wallet remains unlocked until wallet_manager#lock is called or program exit. + /// @param name the name of the wallet to lock. + /// @param password the plaintext password returned from wallet_manager#create. + /// @throws fc::exception if wallet not found or invalid password. void unlock(const std::string& name, const std::string& password); + + /// Import private key into specified wallet. + /// Imports a WIF Private Key into specified wallet. + /// Wallet must be opened and unlocked. + /// @param name the name of the wallet to import into. + /// @param wif_key the WIF Private Key to import, e.g. 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 + /// @throws fc::exception if wallet not found or locked. void import_key(const std::string& name, const std::string& wif_key); private: @@ -33,7 +82,7 @@ private: boost::filesystem::path dir = "."; }; -} -} +} // namespace wallet +} // namespace eos diff --git a/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_plugin.hpp b/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_plugin.hpp index 203b54a37f9dac8a463f646ac044c4f34dc335b2..025c4319b4f2e0f090770a966e045247254c0cce 100644 --- a/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_plugin.hpp +++ b/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_plugin.hpp @@ -22,7 +22,9 @@ public: wallet_plugin(); wallet_plugin(const wallet_plugin&) = delete; wallet_plugin(wallet_plugin&&) = delete; - virtual ~wallet_plugin() = default; + wallet_plugin& operator=(const wallet_plugin&) = delete; + wallet_plugin& operator=(wallet_plugin&&) = delete; + virtual ~wallet_plugin() override = default; virtual void set_program_options(options_description& cli, options_description& cfg) override; void plugin_initialize(const variables_map& options); diff --git a/plugins/wallet_plugin/wallet_manager.cpp b/plugins/wallet_plugin/wallet_manager.cpp index 2f209f7a219c889964a932fd783d3720a9f7825d..eeb0aa3fa02fbc95b36cedd92bf3251ae597e667 100644 --- a/plugins/wallet_plugin/wallet_manager.cpp +++ b/plugins/wallet_plugin/wallet_manager.cpp @@ -110,7 +110,8 @@ void wallet_manager::import_key(const std::string& name, const std::string& wif_ w->import_key(wif_key); } -chain::SignedTransaction wallet_manager::sign_transaction(const chain::SignedTransaction& txn) const { +chain::SignedTransaction +wallet_manager::sign_transaction(const chain::SignedTransaction& txn, const chain::chain_id_type& id) const { chain::SignedTransaction stxn(txn); size_t num_sigs = 0; @@ -123,7 +124,7 @@ chain::SignedTransaction wallet_manager::sign_transaction(const chain::SignedTra if (!key) { FC_THROW("Invalid private key in wallet ${w}", ("w", name)); } - stxn.sign(*key, chain::chain_id_type{}); + stxn.sign(*key, id); ++num_sigs; } } diff --git a/tests/tests/wallet_tests.cpp b/tests/tests/wallet_tests.cpp index 4dadd858429a5ad267def7bee9c8cfd0df1207bb..2002322275489918d83ee054fd7aa7988de92b1b 100644 --- a/tests/tests/wallet_tests.cpp +++ b/tests/tests/wallet_tests.cpp @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(wallet_manager_test) trx.scope = {sender,recipient}; trx.emplaceMessage(config::EosContractName, vector{{sender,"active"}}, "transfer", types::transfer{sender, recipient, amount}); - trx = wm.sign_transaction(trx); + trx = wm.sign_transaction(trx, chain_id_type{}); const auto& pks = trx.get_signature_keys(chain_id_type{}); BOOST_CHECK_EQUAL(3, pks.size()); fc::optional optional_private_key = utilities::wif_to_key(key1);