1212#include < WalletCore/Hash.h>
1313#include < WalletCore/PrivateKey.h>
1414#include < ipfs_pubsub/gossip_pubsub.hpp>
15+ #include < string>
1516
1617#include " base/hexutil.hpp"
1718#include " local_secure_storage/impl/json/JSONSecureStorage.hpp"
@@ -195,6 +196,21 @@ namespace sgns
195196 return nullptr ;
196197 }
197198
199+ std::shared_ptr<GeniusAccount> GeniusAccount::NewFromPublicKey ( TokenID token_id,
200+ std::string_view public_key,
201+ bool full_node )
202+ {
203+ if ( auto response = LoadGeniusAccount ( public_key ); response.has_value () )
204+ {
205+ genius_account_logger ()->debug ( " Loaded existing Genius address" );
206+ return CreateInstanceFromResponse ( token_id, std::move ( response.value () ), full_node );
207+ }
208+
209+ genius_account_logger ()->error ( " Could not load Genius address from storage" );
210+
211+ return nullptr ;
212+ }
213+
198214 std::shared_ptr<GeniusAccount> GeniusAccount::New ( TokenID token_id,
199215 const boost::filesystem::path &base_path,
200216 bool full_node )
@@ -213,6 +229,31 @@ namespace sgns
213229 return GeniusAccount::NewFromMnemonic ( token_id, wallet.getMnemonic (), base_path, full_node );
214230 }
215231
232+ std::vector<std::string> GeniusAccount::GetAvailableAccounts ( const boost::filesystem::path &base_path )
233+ {
234+ auto file_path = SetupStoragePath ( base_path );
235+ genius_account_logger ()->info ( " Secure storage ID path: {}" , file_path.string () );
236+ std::ifstream file ( file_path.string () );
237+
238+ if ( !file.is_open () )
239+ {
240+ genius_account_logger ()->debug ( " Could not find ID file" );
241+ return {};
242+ }
243+
244+ std::vector<std::string> addresses;
245+ std::string line;
246+
247+ while ( std::getline ( file, line ) )
248+ {
249+ addresses.push_back ( std::move ( line ) );
250+ }
251+
252+ genius_account_logger ()->debug ( " Found {} addresses in files" , addresses.size () );
253+
254+ return addresses;
255+ }
256+
216257 outcome::result<GeniusAccount::StorageWithAddress> GeniusAccount::LoadGeniusAccount (
217258 const boost::filesystem::path &base_path )
218259 {
@@ -272,6 +313,37 @@ namespace sgns
272313 std::make_pair ( KeyGenerator::ElGamal ( std::move ( key_seed ) ), std::move ( eth_key ) ) );
273314 }
274315
316+ outcome::result<GeniusAccount::StorageWithAddress> GeniusAccount::LoadGeniusAccount ( std::string_view public_key )
317+ {
318+ OUTCOME_TRY ( std::vector<uint8_t > vec, base::unhex ( public_key ) );
319+
320+ std::shared_ptr<ISecureStorage> storage = std::make_shared<SecureStorageImpl>(
321+ std::string ( SECURE_STORAGE_PREFIX ) + libp2p::multi::detail::encodeBase58 ( vec ) );
322+
323+ auto load_res = storage->Load ( " sgns_key" );
324+ if ( !load_res )
325+ {
326+ genius_account_logger ()->warn ( " Could not load sgns_key from secure storage" );
327+ return std::errc::no_such_file_or_directory;
328+ }
329+
330+ auto key_seed = nil::crypto3::multiprecision::uint256_t ( load_res.value () );
331+ genius_account_logger ()->info ( " Successfully loaded key_seed from storage" );
332+
333+ // Validate loaded key_seed matches stored public key
334+ if ( ethereum::EthereumKeyGenerator ( key_seed ).GetEntirePubValue () != public_key )
335+ {
336+ genius_account_logger ()->error ( " Validation failed: key_seed does not match stored public key" );
337+ return std::errc::bad_message;
338+ }
339+ genius_account_logger ()->info ( " Validation successful: key_seed matches stored public key" );
340+
341+ ethereum::EthereumKeyGenerator eth_key ( key_seed );
342+
343+ return std::make_pair ( std::move ( storage ),
344+ std::make_pair ( KeyGenerator::ElGamal ( std::move ( key_seed ) ), std::move ( eth_key ) ) );
345+ }
346+
275347 outcome::result<GeniusAccount::StorageWithAddress> GeniusAccount::GenerateGeniusAddress (
276348 const char *eth_private_key,
277349 const boost::filesystem::path &base_path )
@@ -403,13 +475,16 @@ namespace sgns
403475 {
404476 if ( auto self = weakptr.lock () )
405477 {
406- std::lock_guard lock ( self->get_cids_mutex_ );
407- if ( self->get_utxos_method_ )
478+ std::vector<std::string> results;
479+ auto utxos = self->GetUTXOManager ().GetUTXOs ( address );
480+ results.reserve ( utxos.size () );
481+
482+ for ( const auto &utxo : utxos )
408483 {
409- return self-> get_utxos_method_ ( address );
484+ results. push_back ( utxo. GetTxID (). toReadableString () );
410485 }
411486
412- return outcome::failure ( AccountMessenger::Error::UTXO_REQUEST_ERROR ) ;
487+ return results ;
413488 }
414489
415490 return outcome::failure ( std::errc::owner_dead );
@@ -541,9 +616,9 @@ namespace sgns
541616 TokenID token_id,
542617 std::shared_ptr<ISecureStorage> storage,
543618 bool full_node ) :
544- eth_keypair_ ( std::move( eth_keypair ) ),
545619 token ( token_id ),
546620 is_full_node_ ( full_node ),
621+ eth_keypair_ ( std::move( eth_keypair ) ),
547622 storage_ ( std::move( storage ) ),
548623 utxo_manager_ (
549624 is_full_node_,
@@ -799,7 +874,7 @@ namespace sgns
799874 if ( cached_nonce_result_.has_value () )
800875 {
801876 auto now = std::chrono::steady_clock::now ();
802- auto cache_age_ms = std::chrono::duration_cast<std::chrono::milliseconds>( now - cached_nonce_timestamp_ )
877+ uint64_t cache_age_ms = std::chrono::duration_cast<std::chrono::milliseconds>( now - cached_nonce_timestamp_ )
803878 .count ();
804879
805880 if ( cache_age_ms < NONCE_CACHE_DURATION_MS )
@@ -984,19 +1059,6 @@ namespace sgns
9841059 has_cid_method_ = nullptr ;
9851060 }
9861061
987- void GeniusAccount::SetGetUTXOsMethod (
988- std::function<outcome::result<std::vector<std::string>>( const std::string & )> method )
989- {
990- std::lock_guard lock ( get_cids_mutex_ );
991- get_utxos_method_ = std::move ( method );
992- }
993-
994- void GeniusAccount::ClearGetUTXOsMethod ()
995- {
996- std::lock_guard lock ( get_cids_mutex_ );
997- get_utxos_method_ = nullptr ;
998- }
999-
10001062 void GeniusAccount::SetGetValidatorWeightMethod (
10011063 std::function<outcome::result<std::optional<uint64_t >>( const std::string & )> method )
10021064 {
0 commit comments