Skip to content

Commit

Permalink
Add has_matching_private_key endpoint into beekeeper
Browse files Browse the repository at this point in the history
  • Loading branch information
Mariusz-Trela authored and vogel76 committed Nov 8, 2023
1 parent 86152e3 commit cd74fbb
Show file tree
Hide file tree
Showing 17 changed files with 173 additions and 3 deletions.
9 changes: 9 additions & 0 deletions programs/beekeeper/beekeeper/beekeeper_wallet_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class beekeeper_api_impl
(get_info)
(create_session)
(close_session)
(has_matching_private_key)
)

std::shared_ptr<beekeeper::beekeeper_wallet_manager> _wallet_mgr;
Expand Down Expand Up @@ -175,6 +176,13 @@ DEFINE_API_IMPL( beekeeper_api_impl, close_session )
return close_session_return();
}

DEFINE_API_IMPL( beekeeper_api_impl, has_matching_private_key )
{
std::lock_guard<std::mutex> guard( mtx );

return { _wallet_mgr->has_matching_private_key( args.token, args.wallet_name, args.public_key ) };
}

} // detail

beekeeper_wallet_api::beekeeper_wallet_api( std::shared_ptr<beekeeper::beekeeper_wallet_manager> wallet_mgr, appbase::application& app ): my( new detail::beekeeper_api_impl( wallet_mgr ) )
Expand All @@ -201,6 +209,7 @@ DEFINE_LOCKLESS_APIS( beekeeper_wallet_api,
(get_info)
(create_session)
(close_session)
(has_matching_private_key)
)

} // beekeeper
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class beekeeper_wallet_api
(get_info)
(create_session)
(close_session)
(has_matching_private_key)
)

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ class BeekeeperInstanceHelper {
return this.#extract(returnedValue);
}

hasMatchingPrivateKey(token, walletName, publicKey) {
const returnedValue = this.instance.has_matching_private_key(token, walletName, publicKey);
const value = this.#extract(returnedValue);

return value.exists;
}

create(sessionToken, walletName) {
const returnedValue = this.instance.create(sessionToken, walletName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,24 @@ test.describe('WASM beekeeper_api tests', () => {
}
}

{
console.log();
console.log("**************************************************************************************");
console.log("Check `has_matching_private_key` endpoint.");
console.log("**************************************************************************************");

/** @type {BeekeeperInstanceHelper} */
const api = new beekeper(args);

{
const walletNo = 1;
api.unlock(api.implicitSessionToken, walletNames[walletNo]);
assert.equal(api.hasMatchingPrivateKey(api.implicitSessionToken, walletNames[walletNo], keys[0][1]), false);
api.importKey(api.implicitSessionToken, walletNames[walletNo], keys[0][0]);
assert.equal(api.hasMatchingPrivateKey(api.implicitSessionToken, walletNames[walletNo], keys[0][1]), true);
}
}

console.log('##########################################################################################');
console.log('## ALL TESTS PASSED ##');
console.log('##########################################################################################');
Expand Down
10 changes: 10 additions & 0 deletions programs/beekeeper/beekeeper_wasm/beekeeper_wasm_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,14 @@ namespace beekeeper {
};
return exception_handler( _method );
}

std::string beekeeper_api::has_matching_private_key( const std::string& token, const std::string& wallet_name, const std::string& public_key )
{
auto _method = [&, this]()
{
has_matching_private_key_return _result{ _impl->app.get_wallet_manager()->has_matching_private_key( token, wallet_name, public_key ) };
return to_string( _result );
};
return exception_handler( _method );
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class beekeeper_api final
std::string sign_digest( const std::string& token, const std::string& sig_digest, const std::string& public_key, const std::string& wallet_name );

std::string get_info( const std::string& token );

std::string has_matching_private_key( const std::string& token, const std::string& wallet_name, const std::string& public_key );
};

}
12 changes: 12 additions & 0 deletions programs/beekeeper/beekeeper_wasm/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,18 @@ EMSCRIPTEN_BINDINGS(beekeeper_api_instance) {
timeout_time: time when wallets will be automatically closed
*/
.function("get_info(token)", &beekeeper_api::get_info)

/*
****testing if a private key corresponding to a public key exists in a wallet****
PARAMS:
token: a token representing a session
wallet_name: a name of wallet
public_key: a public key corresponding to a private key that is stored in a wallet
RESULT:
{"exists":true}
exists: true if a private key exists otherwise false
*/
.function("has_matching_private_key(token, wallet_name, public_key)", &beekeeper_api::has_matching_private_key)
;
}

Expand Down
5 changes: 5 additions & 0 deletions programs/beekeeper/core/beekeeper_wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,11 @@ void beekeeper_wallet::set_wallet_filename(string wallet_filename)
my->_wallet_filename = wallet_filename;
}

bool beekeeper_wallet::has_matching_private_key( const public_key_type& public_key )
{
return my->try_get_private_key( public_key ).has_value();
}

} //beekeeper_wallet

namespace fc
Expand Down
6 changes: 6 additions & 0 deletions programs/beekeeper/core/beekeeper_wallet_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ void beekeeper_wallet_manager::close_session( const string& token, bool allow_cl
--session_cnt;
}

bool beekeeper_wallet_manager::has_matching_private_key( const std::string& token, const std::string& name, const std::string& public_key )
{
sessions->check_timeout( token );
return sessions->get_wallet_manager( token )->has_matching_private_key( name, create_public_key( public_key ) );
}

public_key_type beekeeper_wallet_manager::create_public_key( const std::string& public_key )
{
FC_ASSERT( public_key_size == public_key.size(), "Incorrect size of public key. Expected ${public_key_size}, but got ${public_key_size_2}",
Expand Down
10 changes: 9 additions & 1 deletion programs/beekeeper/core/include/core/beekeeper_wallet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class beekeeper_wallet final : public beekeeper_wallet_base

/** Removes a key from the wallet.
*
* example: remove_key EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
* example: remove_key 6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
*
* @param key the Public Key to remove
*/
Expand All @@ -168,6 +168,14 @@ class beekeeper_wallet final : public beekeeper_wallet_base

std::shared_ptr<detail::beekeeper_impl> my;
void encrypt_keys();

/** Tests if a private key corresponding to a public key exists in a wallet
*
* example: has_matching_private_key 6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
*
* @param key the Public Key to remove
*/
bool has_matching_private_key( const public_key_type& public_key ) override;
};

struct plain_keys {
Expand Down
11 changes: 10 additions & 1 deletion programs/beekeeper/core/include/core/beekeeper_wallet_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class beekeeper_wallet_base

/** Removes a key from the wallet.
*
* example: remove_key EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
* example: remove_key 6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
*
* @param key the Public Key to remove
*/
Expand All @@ -88,6 +88,15 @@ class beekeeper_wallet_base
/** Returns a signature given the digest and public_key, if this wallet can sign via that public key
*/
virtual std::optional<signature_type> try_sign_digest( const digest_type& sig_digest, const public_key_type& public_key ) = 0;

/** Tests if a private key corresponding to a public key exists in a wallet
*
* example: has_matching_private_key 6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
*
* @param a public key to test
* @returns informatio if a private key exists
*/
virtual bool has_matching_private_key( const public_key_type& public_key ) = 0;
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ class beekeeper_wallet_manager
*/
void close_session( const string& token, bool allow_close_all_sessions_action = true );

/// Tests if a private key corresponding to a public key exists in a wallet
/// The wallet must be opened and unlocked.
/// @param name the name of the wallet to test a private key.
/// @param public_key a public key corresponding to a private key that is stored in the wallet
/// @returns true if a private key exists otherwise false
bool has_matching_private_key( const std::string& token, const std::string& name, const std::string& public_key );

private:

seconds_type unlock_timeout = 900;
Expand Down
15 changes: 14 additions & 1 deletion programs/beekeeper/core/include/core/utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ using create_session_return = session_token_type;
using close_session_args = session_token_type;
using close_session_return = void_type;

struct has_matching_private_key_args : public wallet_args
{
std::string public_key;
};

struct has_matching_private_key_return
{
bool exists = false;
};

struct exception
{
static std::pair<std::string, bool> exception_handler( std::function<std::string()>&& method, const std::string& additional_message = "" )
Expand Down Expand Up @@ -239,6 +249,7 @@ namespace fc
void to_variant( const beekeeper::public_key_details& var, fc::variant& vo );
void to_variant( const beekeeper::signature_return& var, fc::variant& vo );
void to_variant( const beekeeper::init_data& var, fc::variant& vo );
void to_variant( const beekeeper::has_matching_private_key_return& var, fc::variant& vo );
}

FC_REFLECT( beekeeper::init_data, (status)(version) )
Expand All @@ -262,4 +273,6 @@ FC_REFLECT( beekeeper::get_public_keys_return, (keys) )
FC_REFLECT_DERIVED( beekeeper::sign_digest_args, (beekeeper::session_token_type), (sig_digest)(public_key)(wallet_name) )
FC_REFLECT( beekeeper::signature_return, (signature) )
FC_REFLECT( beekeeper::create_session_args, (salt)(notifications_endpoint) )
FC_REFLECT_DERIVED( beekeeper::get_public_keys_args, (beekeeper::session_token_type), (wallet_name) )
FC_REFLECT_DERIVED( beekeeper::get_public_keys_args, (beekeeper::session_token_type), (wallet_name) )
FC_REFLECT_DERIVED( beekeeper::has_matching_private_key_args, (beekeeper::wallet_args), (public_key) )
FC_REFLECT( beekeeper::has_matching_private_key_return, (exists) )
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class wallet_manager_impl {
string import_key( const std::string& name, const std::string& wif_key );
void remove_key( const std::string& name, const std::string& password, const std::string& public_key );
signature_type sign_digest( const digest_type& sig_digest, const public_key_type& public_key, const std::optional<std::string>& wallet_name );
bool has_matching_private_key( const std::string& name, const public_key_type& public_key );

private:

Expand Down
5 changes: 5 additions & 0 deletions programs/beekeeper/core/utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,9 @@ namespace fc
vo = v;
}

void to_variant( const beekeeper::has_matching_private_key_return& var, fc::variant& vo )
{
variant v = mutable_variant_object( "exists", var.exists );
vo = v;
}
} // fc
10 changes: 10 additions & 0 deletions programs/beekeeper/core/wallet_manager_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,14 @@ signature_type wallet_manager_impl::sign_digest( const digest_type& sig_digest,
return sign( [&]( const std::unique_ptr<beekeeper_wallet_base>& wallet ){ return wallet->try_sign_digest( sig_digest, public_key ); }, public_key, wallet_name );
}

bool wallet_manager_impl::has_matching_private_key( const std::string& name, const public_key_type& public_key )
{
FC_ASSERT( wallets.count(name), "Wallet not found: ${w}", ("w", name));

auto& w = wallets.at(name);
FC_ASSERT( !w->is_locked(), "Wallet is locked: ${w}", ("w", name));

return w->has_matching_private_key( public_key );
}

} //beekeeper
47 changes: 47 additions & 0 deletions tests/unit/tests/beekeeper_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,53 @@ BOOST_AUTO_TEST_CASE(beekeeper_refresh_timeout)
} FC_LOG_AND_RETHROW()
}

BOOST_AUTO_TEST_CASE(has_matching_private_key_endpoint_test)
{
try {
beekeeper_mgr b_mgr;
b_mgr.remove_wallets();

hive::protocol::serialization_mode_controller::pack_guard guard( hive::protocol::pack_type::hf26 );

auto _private_key_str = "5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n";
auto _public_key_str = "6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4";

auto _private_key_str_2 = "5J8C7BMfvMFXFkvPhHNk2NHGk4zy3jF4Mrpf5k5EzAecuuzqDnn";
auto _public_key_str_2 = "6Pg5jd1w8rXgGoqvpZXy1tHPdz43itPW6L2AGJuw8kgSAbtsxm";

const std::string _host = "127.0.0.1:666";
const uint64_t _timeout = 90;
const uint32_t _session_limit = 64;

appbase::application app;

beekeeper_wallet_manager wm = b_mgr.create_wallet( app, _timeout, _session_limit, [](){} );
BOOST_REQUIRE( wm.start() );

auto _token = wm.create_session( "salt", _host );
auto _password = wm.create( _token, "0", std::optional<std::string>() );

wm.import_key( _token, "0", _private_key_str );

BOOST_REQUIRE_THROW( wm.has_matching_private_key( _token, "pear", _public_key_str ), fc::exception );
BOOST_REQUIRE_THROW( wm.has_matching_private_key( "_token", "0", _public_key_str ), fc::exception );

BOOST_REQUIRE_EQUAL( wm.has_matching_private_key( _token, "0", _public_key_str ), true );
BOOST_REQUIRE_EQUAL( wm.has_matching_private_key( _token, "0", _public_key_str_2 ), false );

wm.import_key( _token, "0", _private_key_str_2 );

BOOST_REQUIRE_EQUAL( wm.has_matching_private_key( _token, "0", _public_key_str ), true );
BOOST_REQUIRE_EQUAL( wm.has_matching_private_key( _token, "0", _public_key_str_2 ), true );

wm.close( _token, "0" );

BOOST_REQUIRE_THROW( wm.has_matching_private_key( _token, "0", _public_key_str ), fc::exception );
BOOST_REQUIRE_THROW( wm.has_matching_private_key( _token, "0", _public_key_str_2 ), fc::exception );

} FC_LOG_AND_RETHROW()
}

BOOST_AUTO_TEST_SUITE_END()

#endif

0 comments on commit cd74fbb

Please sign in to comment.