diff --git a/libraries/chain/include/eos/chain/chain_controller.hpp b/libraries/chain/include/eos/chain/chain_controller.hpp index ef8a1ce0aa33fc0a4c80888d42ef2571adc5daa8..28a485834640635d2b076213177bbb0eb30f511e 100644 --- a/libraries/chain/include/eos/chain/chain_controller.hpp +++ b/libraries/chain/include/eos/chain/chain_controller.hpp @@ -164,7 +164,7 @@ namespace eos { namespace chain { * @return Subset of candidateKeys whose private keys should be used to sign transaction * @throws fc::exception if candidateKeys does not contain all required keys */ - flat_set get_required_keys( const SignedTransaction& trx, const flat_set& candidateKeys)const; + flat_set get_required_keys(const SignedTransaction& trx, const flat_set& candidateKeys)const; bool _push_block( const signed_block& b ); diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index 345000f44ed3b85e309975a655de58847b1020d4..ff30a46caa06fd54fcbaa1eee9f81ca4a13f7b82 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -54,6 +54,7 @@ void chain_api_plugin::plugin_startup() { CHAIN_RO_CALL(get_table_rows), CHAIN_RO_CALL(abi_json_to_bin), CHAIN_RO_CALL(abi_bin_to_json), + CHAIN_RO_CALL(get_required_keys), CHAIN_RW_CALL(push_block), CHAIN_RW_CALL(push_transaction), CHAIN_RW_CALL(push_transactions) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index e37b0608693672cda07e8da39b5c03995865efdf..6585c54782123020a290bac3e2079fe37aafbc42 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include #include @@ -322,5 +324,26 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a return result; } +read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params)const { + + flat_set available_keys; + available_keys.reserve(params.available_keys_wif.size()); + for (const auto& k : params.available_keys_wif) { + available_keys.emplace(public_key_type(k)); + } + + auto pretty_input = db.transaction_from_variant(params.transaction); + auto required_keys_set = db.get_required_keys(pretty_input, available_keys); + + get_required_keys_result result; + result.required_keys_wif.reserve(required_keys_set.size()); + for (const auto& k : required_keys_set) { + result.required_keys_wif.emplace_back(k.operator std::string()); + } + + return result; +} + + } // namespace chain_apis } // namespace eos diff --git a/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp index 78b0eabb8220d019bb8c084d443650bc88873006..276b5c784cefddd94f5c44b4a9a8790c93668874 100644 --- a/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp @@ -7,6 +7,8 @@ #include +#include + namespace fc { class variant; } namespace eos { @@ -14,8 +16,10 @@ namespace eos { using std::unique_ptr; using namespace appbase; using chain::Name; - using fc::optional; using chain::uint128_t; + using chain::public_key_type; + using fc::optional; + using boost::container::flat_set; namespace chain_apis { struct empty{}; @@ -93,6 +97,16 @@ public: abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params )const; + struct get_required_keys_params { + fc::variant transaction; + vector available_keys_wif; + }; + struct get_required_keys_result { + vector required_keys_wif; + }; + + get_required_keys_result get_required_keys( const get_required_keys_params& params)const; + struct get_block_params { string block_num_or_id; @@ -276,3 +290,5 @@ FC_REFLECT( eos::chain_apis::read_only::abi_json_to_bin_params, (code)(action)(a FC_REFLECT( eos::chain_apis::read_only::abi_json_to_bin_result, (binargs)(required_scope)(required_auth) ) FC_REFLECT( eos::chain_apis::read_only::abi_bin_to_json_params, (code)(action)(binargs) ) FC_REFLECT( eos::chain_apis::read_only::abi_bin_to_json_result, (args)(required_scope)(required_auth) ) +FC_REFLECT( eos::chain_apis::read_only::get_required_keys_params, (available_keys_wif) ) +FC_REFLECT( eos::chain_apis::read_only::get_required_keys_result, (required_keys_wif) ) 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 91e6b4cf3f0fb3117fda146cba7c30e59f63da03..e5d326de393b7368d1b7f73464e437ba131c203d 100644 --- a/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_manager.hpp +++ b/plugins/wallet_plugin/include/eos/wallet_plugin/wallet_manager.hpp @@ -60,8 +60,7 @@ public: /// @return A list of wallet names with " *" appended if the wallet is unlocked. std::vector list_wallets(); - /// @return A list of unlocked wallet names and their private keys. - /// Wallet name entry followed by private key entries. + /// @return A list of private keys from all unlocked wallets in wif format. std::vector list_keys(); /// Locks all the unlocked wallets. diff --git a/plugins/wallet_plugin/wallet_manager.cpp b/plugins/wallet_plugin/wallet_manager.cpp index 8a9ff2514a55fc7386cf1113cdc95cbe3df56374..149494378e6bc42962c1b7919816e6cb122d357a 100644 --- a/plugins/wallet_plugin/wallet_manager.cpp +++ b/plugins/wallet_plugin/wallet_manager.cpp @@ -78,7 +78,6 @@ std::vector wallet_manager::list_keys() { std::vector result; for (const auto& i : wallets) { if (!i.second->is_locked()) { - result.emplace_back(i.first); const auto& keys = i.second->list_keys(); for (const auto& i : keys) { result.emplace_back(i.second); diff --git a/tests/tests/wallet_tests.cpp b/tests/tests/wallet_tests.cpp index 91a062bf63d89c68df4246681293ac8717b6c0a8..3bcad7f30729bee184efc7c2090975f703c09933 100644 --- a/tests/tests/wallet_tests.cpp +++ b/tests/tests/wallet_tests.cpp @@ -85,14 +85,14 @@ BOOST_AUTO_TEST_CASE(wallet_manager_test) BOOST_CHECK(!pw.empty()); BOOST_CHECK_EQUAL(0, pw.find("PW")); // starts with PW BOOST_CHECK_EQUAL(1, wm.list_wallets().size()); - BOOST_CHECK_EQUAL(1, wm.list_keys().size()); // wallet name only + BOOST_CHECK_EQUAL(0, wm.list_keys().size()); // no keys BOOST_CHECK(wm.list_wallets().at(0).find("*") != std::string::npos); wm.lock("test"); BOOST_CHECK(wm.list_wallets().at(0).find("*") == std::string::npos); wm.unlock("test", pw); BOOST_CHECK(wm.list_wallets().at(0).find("*") != std::string::npos); wm.import_key("test", key1); - BOOST_CHECK_EQUAL(2, wm.list_keys().size()); // name and key + BOOST_CHECK_EQUAL(1, wm.list_keys().size()); auto keys = wm.list_keys(); BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), key1) != keys.cend()); wm.import_key("test", key2); @@ -102,14 +102,14 @@ BOOST_AUTO_TEST_CASE(wallet_manager_test) wm.lock("test"); BOOST_CHECK_EQUAL(0, wm.list_keys().size()); wm.unlock("test", pw); - BOOST_CHECK_EQUAL(3, wm.list_keys().size()); + BOOST_CHECK_EQUAL(2, wm.list_keys().size()); wm.lock_all(); BOOST_CHECK_EQUAL(0, wm.list_keys().size()); BOOST_CHECK(wm.list_wallets().at(0).find("*") == std::string::npos); auto pw2 = wm.create("test2"); BOOST_CHECK_EQUAL(2, wm.list_wallets().size()); - BOOST_CHECK_EQUAL(1, wm.list_keys().size()); // wallet name only + BOOST_CHECK_EQUAL(0, wm.list_keys().size()); wm.import_key("test2", key3); keys = wm.list_keys(); BOOST_CHECK(std::find(keys.cbegin(), keys.cend(), key1) == keys.cend()); @@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(wallet_manager_test) optional_private_key = utilities::wif_to_key(key3); BOOST_CHECK(find(pks.cbegin(), pks.cend(), optional_private_key->get_public_key()) != pks.cend()); - BOOST_CHECK_EQUAL(5, wm.list_keys().size()); + BOOST_CHECK_EQUAL(3, wm.list_keys().size()); wm.set_timeout(chrono::seconds(0)); BOOST_CHECK_EQUAL(0, wm.list_keys().size());