Skip to content

account/GeniusNode.hpp

Namespaces

Name
sgns

Classes

Name
struct DevConfig
class sgns::GeniusNode

Types

Name
typedef struct DevConfig DevConfig_st

Functions

Name
OUTCOME_HPP_DECLARE_ERROR_2(sgns , GeniusNode::Error )

Attributes

Name
DevConfig_st DEV_CONFIG

Defines

Name
OUTGOING_TIMEOUT_MILLISECONDS
INCOMING_TIMEOUT_MILLISECONDS

Types Documentation

typedef DevConfig_st

typedef struct DevConfig DevConfig_st;

Functions Documentation

function OUTCOME_HPP_DECLARE_ERROR_2

OUTCOME_HPP_DECLARE_ERROR_2(
    sgns ,
    GeniusNode::Error 
)

Attributes Documentation

variable DEV_CONFIG

DevConfig_st DEV_CONFIG;

Macros Documentation

define OUTGOING_TIMEOUT_MILLISECONDS

#define OUTGOING_TIMEOUT_MILLISECONDS 50000

define INCOMING_TIMEOUT_MILLISECONDS

#define INCOMING_TIMEOUT_MILLISECONDS 150000

Source code

#ifndef _GENIUS_NODE_HPP_
#define _GENIUS_NODE_HPP_

#include <memory>
#include <cstdint>
#include <functional>
#include <vector>
#include <thread>
#include <optional>

#include <boost/asio.hpp>
#include <spdlog/sinks/basic_file_sink.h>
#include <libp2p/log/logger.hpp>
#include <libp2p/multi/multibase_codec/multibase_codec_impl.hpp>
#include <libp2p/multi/content_identifier_codec.hpp>

#include "account/GeniusAccount.hpp"
#include "base/buffer.hpp"
#include "account/TransactionManager.hpp"
#include <ipfs_lite/ipfs/graphsync/graphsync.hpp>
#include "crypto/hasher/hasher_impl.hpp"
#include "processing/impl/processing_core_impl.hpp"
#include "processing/impl/processing_subtask_result_storage_impl.hpp"
#include "processing/processing_service.hpp"
#include "singleton/IComponent.hpp"
#include "processing/impl/processing_task_queue_impl.hpp"
#include "coinprices/coinprices.hpp"
#include "blockchain/Blockchain.hpp"
#include <boost/algorithm/string/replace.hpp>
#include <ipfs_lite/ipfs/graphsync/impl/network/network.hpp>
#include <processingbase/ProcessingManager.hpp>

typedef struct DevConfig
{
    std::string Addr;
    std::string Cut;
    std::string TokenValueInGNUS;
    TokenID     TokenID;
    std::string BaseWritePath;
} DevConfig_st;

extern DevConfig_st DEV_CONFIG;

#define OUTGOING_TIMEOUT_MILLISECONDS 50000  // just communication time
#define INCOMING_TIMEOUT_MILLISECONDS 150000 // communication + verify proof

namespace sgns
{
    class GeniusNode : public IComponent, public std::enable_shared_from_this<GeniusNode>
    {
    public:
        static std::shared_ptr<GeniusNode> New( const DevConfig_st &dev_config,
                                                bool                autodht      = true,
                                                bool                isprocessor  = true,
                                                uint16_t            base_port    = 40001,
                                                bool                is_full_node = false,
                                                bool                use_upnp     = true );

        static std::shared_ptr<GeniusNode> New( const DevConfig_st &dev_config,
                                                const char         *eth_private_key,
                                                bool                autodht      = true,
                                                bool                isprocessor  = true,
                                                uint16_t            base_port    = 40001,
                                                bool                is_full_node = false,
                                                bool                use_upnp     = true );

        static std::shared_ptr<GeniusNode> NewFromMnemonic( const DevConfig_st &dev_config,
                                                            const std::string  &mnemonic,
                                                            bool                autodht      = true,
                                                            bool                isprocessor  = true,
                                                            uint16_t            base_port    = 40001,
                                                            bool                is_full_node = false,
                                                            bool                use_upnp     = true );

        ~GeniusNode() override;

        enum class NodeState : uint8_t
        {
            CREATING = 0,
            MIGRATING_DATABASE,
            INITIALIZING_DATABASE,
            INITIALIZING_PROCESSING,
            INITIALIZING_BLOCKCHAIN,
            INITIALIZING_TRANSACTIONS,
            READY,
        };

        enum class Error : uint8_t
        {
            INSUFFICIENT_FUNDS        = 1,  
            DATABASE_WRITE_ERROR      = 2,  
            INVALID_TRANSACTION_HASH  = 3,  
            INVALID_CHAIN_ID          = 4,  
            INVALID_TOKEN_ID          = 5,  
            TOKEN_ID_MISMATCH         = 6,  
            PROCESS_COST_ERROR        = 7,  
            PROCESS_INFO_MISSING      = 8,  
            INVALID_JSON              = 9,  
            INVALID_BLOCK_PARAMETERS  = 10, 
            NO_PROCESSOR              = 11, 
            NO_PRICE                  = 12, 
            TRANSACTIONS_NOT_READY    = 13, 
            TRANSACTION_NOT_FINALIZED = 14, 
            TRANSACTION_FAILED        = 15, 
        };

#ifdef SGNS_DEBUG
        static constexpr uint64_t TIMEOUT_ESCROW_PAY = 50000;
        static constexpr uint64_t TIMEOUT_TRANSFER   = 50000;
        static constexpr uint64_t TIMEOUT_MINT       = 50000;
#else
        static constexpr uint64_t TIMEOUT_ESCROW_PAY = 30000;
        static constexpr uint64_t TIMEOUT_TRANSFER   = 30000;
        static constexpr uint64_t TIMEOUT_MINT       = 30000;
#endif
        outcome::result<void> SelectAccount( std::string_view public_address );

        outcome::result<std::string> ProcessImage( const std::string &jsondata );

        uint64_t GetProcessCost( std::shared_ptr<sgns::sgprocessing::ProcessingManager> &procmgr );

        outcome::result<double> GetGNUSPrice();

        std::string GetName() override
        {
            return "GeniusNode";
        }

        std::string GetVersion();

        outcome::result<std::string> MintTokens( uint64_t           amount,
                                                 const std::string &transaction_hash,
                                                 const std::string &chainid,
                                                 TokenID            tokenid,
                                                 std::string        destination = "" );

        outcome::result<std::pair<std::string, uint64_t>> MintTokens( uint64_t                  amount,
                                                                      const std::string        &transaction_hash,
                                                                      const std::string        &chainid,
                                                                      TokenID                   tokenid,
                                                                      std::string               destination,
                                                                      std::chrono::milliseconds timeout );

        void AddPeer( const std::string &peer );
        void RefreshUPNP( uint16_t pubsubport );

        uint64_t GetBalance();
        uint64_t GetBalance( TokenID token_id );
        uint64_t GetBalance( const std::string &address );
        uint64_t GetBalance( TokenID token_id, const std::string &address );

        [[nodiscard]] const std::vector<std::vector<uint8_t>> GetInTransactions() const
        {
            auto manager_result = GetTransactionManager();
            if ( !manager_result.has_value() )
            {
                return {};
            }
            return manager_result.value()->GetInTransactions();
        }

        [[nodiscard]] const std::vector<std::vector<uint8_t>> GetOutTransactions() const
        {
            auto manager_result = GetTransactionManager();
            if ( !manager_result.has_value() )
            {
                return {};
            }
            return manager_result.value()->GetOutTransactions();
        }

        std::string GetAddress() const
        {
            return account_->GetAddress();
        }

        TokenID GetTokenID() const
        {
            return dev_config_.TokenID;
        }

        [[nodiscard]] processing::ProcessingServiceImpl::ProcessingStatus GetProcessingStatus() const
        {
            return processing_service_ == nullptr ? processing::ProcessingServiceImpl::ProcessingStatus(
                                                        processing::ProcessingServiceImpl::Status::DISABLED,
                                                        0.0f )
                                                  : processing_service_->GetProcessingStatus();
        }

        outcome::result<std::pair<std::string, uint64_t>> TransferFunds( uint64_t                  amount,
                                                                         const std::string        &destination,
                                                                         TokenID                   token_id,
                                                                         std::chrono::milliseconds timeout );

        outcome::result<std::string> TransferFunds( uint64_t amount, const std::string &destination, TokenID token_id );

        outcome::result<std::string> PayDev( uint64_t amount, TokenID token_id );

        outcome::result<std::pair<std::string, uint64_t>> PayDev( uint64_t                  amount,
                                                                  TokenID                   token_id,
                                                                  std::chrono::milliseconds timeout );

        outcome::result<std::pair<TransactionManager::TransactionStatus, uint64_t>> WaitForFinalized(
            const std::string        &tx_id,
            std::chrono::milliseconds timeout );

        std::optional<TransactionManager::TransactionStatus> IsFinalized( const std::string &tx_id );

        std::shared_ptr<ipfs_pubsub::GossipPubSub> GetPubSub()
        {
            return pubsub_;
        }

        outcome::result<std::string> FormatTokens( uint64_t amount, const TokenID tokenId );

        outcome::result<uint64_t> ParseTokens( const std::string &str, const TokenID tokenId );

        void PrintDataStore() const;
        void StopProcessing();
        void StartProcessing();

        outcome::result<std::map<std::string, double>> GetCoinprice( const std::vector<std::string> &tokenIds );
        outcome::result<std::map<std::string, std::map<int64_t, double>>> GetCoinPriceByDate(
            const std::vector<std::string> &tokenIds,
            const std::vector<int64_t>     &timestamps );
        outcome::result<std::map<std::string, std::map<int64_t, double>>> GetCoinPricesByDateRange(
            const std::vector<std::string> &tokenIds,
            int64_t                         from,
            int64_t                         to );
        // Wait for an incoming transaction to be processed with a timeout
        TransactionManager::TransactionStatus WaitForTransactionIncoming( const std::string        &txId,
                                                                          std::chrono::milliseconds timeout );
        // Wait for a outgoing transaction to be processed with a timeout
        TransactionManager::TransactionStatus WaitForTransactionOutgoing( const std::string        &txId,
                                                                          std::chrono::milliseconds timeout );

        TransactionManager::TransactionStatus WaitForEscrowRelease( const std::string        &originalEscrowId,
                                                                    std::chrono::milliseconds timeout );

        TransactionManager::State GetTransactionManagerState() const;

        TransactionManager::TransactionStatus GetTransactionStatus( const std::string &txId ) const;

        void SetAuthorizedFullNodeAddress( const std::string &pub_address );

        const std::string &GetAuthorizedFullNodeAddress() const;

        NodeState GetState() const
        {
            return state_.load();
        }

    protected:
        friend class TransactionSyncTest;

        void SendTransactionAndProof( std::shared_ptr<IGeniusTransactions> tx, std::vector<uint8_t> proof );
        void ConfigureTransactionFilterTimeoutsMs( uint64_t timeframe_limit_ms, uint64_t mutability_window_ms );

        std::string                    write_base_path_;
        std::shared_ptr<GeniusAccount> account_;

    private:
        std::shared_ptr<boost::asio::io_context>                                 io_;
        boost::asio::executor_work_guard<boost::asio::io_context::executor_type> io_work_guard_;
        std::shared_ptr<crdt::GlobalDB>                                          tx_globaldb_;
        std::shared_ptr<crdt::GlobalDB>                                          job_globaldb_;
        std::shared_ptr<ipfs_pubsub::GossipPubSub>                               pubsub_;
        std::shared_ptr<TransactionManager>                                      transaction_manager_;
        std::shared_ptr<processing::ProcessingTaskQueueImpl>                     task_queue_;
        std::shared_ptr<processing::ProcessingCoreImpl>                          processing_core_;
        std::shared_ptr<processing::ProcessingServiceImpl>                       processing_service_;
        std::shared_ptr<processing::SubTaskResultStorageImpl>                    task_result_storage_;
        std::shared_ptr<soralog::LoggingSystem>                                  logging_system_;
        bool                                                                     autodht_;
        bool                                                                     isprocessor_;
        bool                                                                     is_full_node_;
        base::Logger                                                             node_logger_;
        DevConfig_st                                                             dev_config_;
        std::string                                                              gnus_network_full_path_;
        std::string                                                              processing_channel_topic_;
        std::string                                                              processing_grid_chanel_topic_;
        uint16_t                                                                 pubsubport_;
        std::shared_ptr<Blockchain>                                              blockchain_;

        GeniusNode( const DevConfig_st            &dev_config,
                    std::shared_ptr<GeniusAccount> account,
                    bool                           autodht,
                    bool                           isprocessor,
                    uint16_t                       base_port,
                    bool                           is_full_node,
                    bool                           use_upnp );

        void         InitOpenSSL();
        bool         InitLoggers( const std::string &base_path );
        base::Logger ConfigureLogger( const std::string        &tag,
                                      const std::string        &logdir,
                                      spdlog::level::level_enum level );
        bool         InitNetwork( uint16_t base_port, bool is_full_node );
        bool         InitUPNP();
        bool         InitDatabase();
        bool         InitProcessingModules();
        void         BeginDBInitialization();
        void         StateTransition( NodeState next_state );
        void         MigrateDatabase( std::function<void( outcome::result<void> )> callback );
        void         ScheduleMigrationRetry();
        void         ScheduleBlockchainRetry();
        outcome::result<std::shared_ptr<TransactionManager>> GetTransactionManager() const;
        outcome::result<void>                                CheckProcessValidity( const std::string &jsondata );

        void DHTInit();

        struct PriceInfo
        {
            double                                             price;
            std::chrono::time_point<std::chrono::system_clock> lastUpdate;
        };

        std::map<std::string, PriceInfo>                   m_tokenPriceCache;
        const std::chrono::minutes                         m_cacheValidityDuration{ 1 };
        std::chrono::time_point<std::chrono::system_clock> m_lastApiCall{};
        static constexpr std::chrono::seconds              MIN_API_CALL_INTERVAL{ 5 };

        static constexpr size_t                                         DEFAULT_IO_THREADS = 4;
        size_t                                                          io_thread_count_{ DEFAULT_IO_THREADS };
        std::vector<std::thread>                                        io_threads_;
        std::thread                                                     upnp_thread;
        std::atomic<bool>                                               stop_upnp{ false };
        std::string                                                     base58key_;
        std::shared_ptr<libp2p::basic::Scheduler>                       scheduler_;
        std::shared_ptr<ipfs_lite::ipfs::graphsync::RequestIdGenerator> generator_;
        std::shared_ptr<ipfs_lite::ipfs::graphsync::Network>            graphsyncnetwork_;

        std::unique_ptr<boost::asio::thread_pool> processing_callback_pool_;

        std::atomic<NodeState> state_{ NodeState::CREATING };
        bool                   use_upnp_;

        outcome::result<std::pair<std::string, uint64_t>> PayEscrow(
            const std::string                       &escrow_path,
            const SGProcessing::TaskResult          &taskresult,
            std::shared_ptr<crdt::AtomicTransaction> crdt_transaction,
            std::chrono::milliseconds                timeout = std::chrono::milliseconds( TIMEOUT_ESCROW_PAY ) );

        void ProcessingDone( const std::string &task_id, const SGProcessing::TaskResult &taskresult );
        void ProcessingError( const std::string &task_id );

        void RotateLogFiles( const std::string &base_path );
        outcome::result<uint64_t> ParseBlockSize( const std::string &json_data );

        void TransactionStateChanged( TransactionManager::State old_state, TransactionManager::State new_state );

        static constexpr std::string_view DB_PATH         = "bc-%d/";
        static constexpr std::uint16_t    MAIN_NET        = 369;
        static constexpr std::uint16_t    TEST_NET        = 963;
        static constexpr std::size_t      MAX_NODES_COUNT = 1;

        static constexpr std::string_view PROCESSING_GRID_CHANNEL = "SGNUS.Jobs.Channel";
        static constexpr std::string_view PROCESSING_CHANNEL      = "SGNUS.Processing.Channel";
        static constexpr std::string_view GNUS_NETWORK_PATH       = "SuperGNUSNode.Node";

        static std::string GetLoggingSystem( const std::string &base_path )
        {
            std::string config( R"(
# ----------------
sinks:
    - name: file
      type: file
      capacity: 1000
      path: [basepath]/sgnslog.log
groups:
    - name: SuperGeniusNode
      sink: file
      level: error
      children:
        - name: libp2p
        - name: Gossip
        - name: yx-stream
# ----------------
  )" );

            boost::replace_all( config, "[basepath]", base_path );
            return config;
        }
    };
}

OUTCOME_HPP_DECLARE_ERROR_2( sgns, GeniusNode::Error );

#endif

Updated on 2026-04-15 at 11:00:39 -0700