Skip to content

src/account/GeniusAccount.hpp

Header file of the Genius account class. More...

Namespaces

Name
sgns
sgns::ipfs_pubsub
sgns::crdt
boost::multiprecision

Classes

Name
class sgns::GeniusAccount
struct sgns::GeniusAccount::Credentials

Detailed Description

Header file of the Genius account class.

Date: 2024-03-11 Henrique A. Klein ([email protected])

Source code

#pragma once

#include <array>
#include <memory>
#include <string>
#include <vector>
#include <shared_mutex>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <functional>
#include <optional>
#include <set>

#include <boost/multiprecision/cpp_int.hpp>

#include <ProofSystem/ElGamalKeyGenerator.hpp>
#include <ProofSystem/EthereumKeyGenerator.hpp>

#include "account/TokenID.hpp"
#include "local_secure_storage/ISecureStorage.hpp"
#include "outcome/outcome.hpp"

#include <unordered_set>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

namespace sgns
{
    using namespace boost::multiprecision;

    namespace ipfs_pubsub
    {
        class GossipPubSub;
    }

    namespace crdt
    {
        class GlobalDB;
    }
    class AccountMessenger;

    class GeniusAccount : public std::enable_shared_from_this<GeniusAccount>
    {
    public:
        using StorageWithAddress = std::pair<std::shared_ptr<ISecureStorage>,
                                             std::pair<KeyGenerator::ElGamal, ethereum::EthereumKeyGenerator>>;

        struct Credentials
        {
            std::string email;
            std::string password;
        };

        static const std::array<uint8_t, 32> ELGAMAL_PUBKEY_PREDEFINED;      
        static constexpr uint64_t            NONCE_CACHE_DURATION_MS = 5000; 

        static std::shared_ptr<GeniusAccount> New( TokenID                        token_id,
                                                   const char                    *eth_private_key,
                                                   const boost::filesystem::path &base_path,
                                                   bool                           full_node = false );

        static std::shared_ptr<GeniusAccount> New( TokenID                        token_id,
                                                   const Credentials             &credentials,
                                                   const boost::filesystem::path &base_path,
                                                   bool                           full_node = false );

        static std::shared_ptr<GeniusAccount> New( TokenID                        token_id,
                                                   const boost::filesystem::path &base_path,
                                                   bool                           full_node = false );

        bool InitMessenger( std::shared_ptr<ipfs_pubsub::GossipPubSub> pubsub );

        bool ConfigureMessengerHandlers( std::shared_ptr<crdt::GlobalDB> global_db );

        ~GeniusAccount();

        [[nodiscard]] std::string GetAddress() const;

        [[nodiscard]] TokenID GetToken() const;

        [[nodiscard]] std::string GetNonce() const
        {
            return std::to_string( GetProposedNonce() );
        }

        static bool VerifySignature( const std::string          &address,
                                     std::string_view            sig,
                                     const std::vector<uint8_t> &data );

        std::vector<uint8_t> Sign( const std::vector<uint8_t> &data ) const;

        void SetLocalConfirmedNonce( uint64_t nonce );

        void SetPeerConfirmedNonce( uint64_t nonce, const std::string &address );

        void RollBackPeerConfirmedNonce( uint64_t nonce, const std::string &address );

        outcome::result<uint64_t> GetPeerNonce( const std::string &address ) const;

        outcome::result<uint64_t> GetLocalConfirmedNonce() const;

        outcome::result<uint64_t> GetConfirmedNonce( uint64_t timeout_ms ) const;

        uint64_t GetProposedNonce() const;

        uint64_t ReserveNextNonce();

        void ReleaseNonce( uint64_t nonce );

        outcome::result<void> RequestGenesis(
            uint64_t                                            timeout_ms = 8000,
            std::function<void( outcome::result<std::string> )> callback   = nullptr ) const;
        outcome::result<void> RequestAccountCreation(
            uint64_t                                            timeout_ms,
            std::function<void( outcome::result<std::string> )> callback ) const;
        outcome::result<void> RequestRegularBlock(
            uint64_t                                            timeout_ms,
            const std::string                                  &cid,
            std::function<void( outcome::result<std::string> )> callback = nullptr ) const;
        outcome::result<void> RequestHeads( const std::unordered_set<std::string> &topics ) const;

        static outcome::result<StorageWithAddress> GenerateGeniusAddress( const char *eth_private_key,
                                                                          const boost::filesystem::path &base_path );

        static outcome::result<StorageWithAddress> GenerateGeniusAddress( const Credentials             &credentials,
                                                                          const boost::filesystem::path &base_path );

    protected:
        friend class Blockchain;
        void SetGetBlockChainCIDMethod(
            std::function<outcome::result<std::string>( uint8_t, const std::string & )> method );
        void ClearGetBlockChainCIDMethod();
        void SetHasBlockCidMethod( std::function<outcome::result<bool>( const std::string & )> method );
        void ClearHasBlockCidMethod();

    private:
        static constexpr size_t SIGNATURE_EXP_SIZE = 64; 

        static outcome::result<StorageWithAddress> LoadGeniusAccount( const boost::filesystem::path &base_path );

        static std::shared_ptr<GeniusAccount> CreateInstanceFromResponse( TokenID            token_id,
                                                                          StorageWithAddress response_value,
                                                                          bool               full_node );

        TokenID token;         
        bool    is_full_node_; 

        std::shared_ptr<ethereum::EthereumKeyGenerator> eth_keypair_;      
        std::shared_ptr<KeyGenerator::ElGamal>          elgamal_address_;  
        std::shared_ptr<ISecureStorage>                 storage_;          
        std::unordered_map<std::string, uint64_t>       confirmed_nonces_; 
        mutable std::shared_mutex                       nonce_mutex_;      
        std::set<uint64_t>                              pending_nonces_;   
        std::optional<uint64_t>                         local_confirmed_nonce_; 
        std::shared_ptr<AccountMessenger>               messenger_;             

        // Nonce request tracking
        mutable std::mutex              nonce_request_mutex_; 
        mutable std::condition_variable nonce_request_cv_;    
        mutable bool nonce_request_in_progress_;              
        mutable std::optional<outcome::result<uint64_t>>
            cached_nonce_result_; 
        mutable std::chrono::steady_clock::time_point
                   cached_nonce_timestamp_; 
        std::mutex get_cids_mutex_;         
        std::function<outcome::result<std::string>( uint8_t, const std::string & )>
            get_cids_method_; 
        std::function<outcome::result<bool>( const std::string & )> has_cid_method_; 

        uint64_t GetNextNonceLocked() const;

        GeniusAccount( TokenID token_id, std::shared_ptr<ISecureStorage> storage, bool full_node );
    };
}

Updated on 2026-03-04 at 13:10:44 -0800