├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CMakeSettings.msvs2019-vcpkg.json ├── LICENSE ├── README.md ├── api ├── CMakeLists.txt ├── api_gen │ └── CMakeLists.txt ├── executor_gen │ └── CMakeLists.txt ├── include │ ├── apidiaghandler.hpp │ ├── apihandler.hpp │ ├── csconnector │ │ └── csconnector.hpp │ ├── csstats.hpp │ ├── debuglog.hpp │ ├── dumbcv.hpp │ ├── executor.hpp │ ├── executormanager.hpp │ ├── profiler │ │ ├── profiler.hpp │ │ ├── profilereventhandler.hpp │ │ └── profilerprocessor.hpp │ ├── serializer.hpp │ ├── stdafx.h │ └── tokens.hpp ├── src │ ├── apidiaghandler.cpp │ ├── apihandler.cpp │ ├── csconnector.cpp │ ├── csstats.cpp │ ├── dumbcv.cpp │ ├── executor.cpp │ ├── executormanager.cpp │ ├── profiler.cpp │ ├── profilerprocessor.cpp │ ├── stdafx.cpp │ └── tokens.cpp └── variant_gen │ ├── CMakeLists.txt │ └── variant_aux.cpp ├── benchmark ├── CMakeLists.txt ├── allocatorbench │ ├── CMakeLists.txt │ └── main.cpp ├── include │ ├── benchmark.hpp │ ├── framework.hpp │ └── timeoutexception.hpp ├── lmdbbench │ ├── CMakeLists.txt │ └── main.cpp ├── signalsbench │ ├── CMakeLists.txt │ └── main.cpp ├── src │ └── benchmark.cpp └── testbench │ ├── CMakeLists.txt │ ├── instance.cpp │ └── instance.hpp ├── client ├── CMakeLists.txt ├── config │ ├── CMakeLists.txt │ ├── config.cpp │ ├── config.hpp │ ├── observer.cpp │ └── observer.hpp ├── include │ └── client │ │ ├── cmdlineargs.hpp │ │ ├── params.hpp │ │ ├── peer.hpp │ │ ├── stdafx.h │ │ └── version.hpp └── src │ ├── main.cpp │ ├── peer.cpp │ ├── stdafx.cpp │ └── version.cpp.in ├── cmake └── Modules │ └── FindGMock.cmake ├── codingstyle.md ├── csdb ├── CMakeLists.txt ├── benchmark │ ├── CMakeLists.txt │ └── csdb_benchmark_main.cpp ├── include │ └── csdb │ │ ├── address.hpp │ │ ├── amount.hpp │ │ ├── amount_commission.hpp │ │ ├── csdb.hpp │ │ ├── currency.hpp │ │ ├── database.hpp │ │ ├── database_berkeleydb.hpp │ │ ├── internal │ │ ├── endian.hpp │ │ ├── math128ce.hpp │ │ ├── shared_data.hpp │ │ ├── shared_data_ptr_implementation.hpp │ │ ├── sorted_array_set.hpp │ │ ├── types.hpp │ │ └── utils.hpp │ │ ├── pool.hpp │ │ ├── storage.hpp │ │ ├── transaction.hpp │ │ ├── user_field.hpp │ │ └── wallet.hpp ├── src │ ├── address.cpp │ ├── amount.cpp │ ├── amount_commission.cpp │ ├── binary_streams.cpp │ ├── binary_streams.hpp │ ├── csdb.cpp │ ├── currency.cpp │ ├── database.cpp │ ├── database_berkeleydb.cpp │ ├── integral_encdec.cpp │ ├── integral_encdec.hpp │ ├── pool.cpp │ ├── priv_crypto.cpp │ ├── priv_crypto.hpp │ ├── storage.cpp │ ├── transaction.cpp │ ├── transaction_p.hpp │ ├── user_field.cpp │ ├── utils.cpp │ └── wallet.cpp └── unittests │ ├── CMakeLists.txt │ ├── csdb_unit_tests_address.cpp │ ├── csdb_unit_tests_amount.cpp │ ├── csdb_unit_tests_binary_streams.cpp │ ├── csdb_unit_tests_database.cpp │ ├── csdb_unit_tests_database_leveldb.cpp │ ├── csdb_unit_tests_endian.cpp │ ├── csdb_unit_tests_environment.cpp │ ├── csdb_unit_tests_environment.h │ ├── csdb_unit_tests_integral_encdec.cpp │ ├── csdb_unit_tests_main.cpp │ ├── csdb_unit_tests_math128ce.cpp │ ├── csdb_unit_tests_pool.cpp │ ├── csdb_unit_tests_shared_data.cpp │ ├── csdb_unit_tests_shared_data.h │ ├── csdb_unit_tests_shared_data_p.cpp │ ├── csdb_unit_tests_sorted_array_set.cpp │ ├── csdb_unit_tests_storage.cpp │ ├── csdb_unit_tests_transaction.cpp │ ├── csdb_unit_tests_user_field.cpp │ ├── csdb_unit_tests_utils.cpp │ └── csdb_unit_tests_wallet.cpp ├── csnode ├── CMakeLists.txt ├── include │ └── csnode │ │ ├── address_serializer.hpp │ │ ├── apihandler_serializer.hpp │ │ ├── bitheap.hpp │ │ ├── blockchain.hpp │ │ ├── blockchain_serializer.hpp │ │ ├── blockhashes.hpp │ │ ├── blockvalidator.hpp │ │ ├── blockvalidatorplugins.hpp │ │ ├── caches_serialization_manager.hpp │ │ ├── compressor.hpp │ │ ├── configholder.hpp │ │ ├── confirmationlist.hpp │ │ ├── conveyer.hpp │ │ ├── cyclicbuffer.hpp │ │ ├── datastream.hpp │ │ ├── eventreport.hpp │ │ ├── fee.hpp │ │ ├── idatastream.hpp │ │ ├── itervalidator.hpp │ │ ├── multiwallets.hpp │ │ ├── node.hpp │ │ ├── nodecore.hpp │ │ ├── nodeutils.hpp │ │ ├── odatastream.hpp │ │ ├── packetqueue.hpp │ │ ├── poolcache.hpp │ │ ├── poolsynchronizer.hpp │ │ ├── roundpackage.hpp │ │ ├── roundstat.hpp │ │ ├── roundstat_serializer.hpp │ │ ├── sendcachedata.hpp │ │ ├── serializers_helper.hpp │ │ ├── smartcontracts_serializer.hpp │ │ ├── staking.hpp │ │ ├── tokens_serializer.hpp │ │ ├── transactionsindex.hpp │ │ ├── transactionsiterator.hpp │ │ ├── transactionspacket.hpp │ │ ├── transactionstail.hpp │ │ ├── transactionsvalidator.hpp │ │ ├── walletscache.hpp │ │ ├── walletscache_serializer.hpp │ │ ├── walletsids.hpp │ │ ├── walletsids_serializer.hpp │ │ └── walletsstate.hpp └── src │ ├── apihandler_serializer.cpp │ ├── blockchain.cpp │ ├── blockchain_serializer.cpp │ ├── blockhashes.cpp │ ├── blockvalidator.cpp │ ├── blockvalidatorplugins.cpp │ ├── caches_serialization_manager.cpp │ ├── configholder.cpp │ ├── confirmationlist.cpp │ ├── conveyer.cpp │ ├── eventreport.cpp │ ├── fee.cpp │ ├── itervalidator.cpp │ ├── multiwallets.cpp │ ├── node.cpp │ ├── nodecore.cpp │ ├── nodeutils.cpp │ ├── packetqueue.cpp │ ├── poolcache.cpp │ ├── poolsynchronizer.cpp │ ├── roundpackage.cpp │ ├── roundstat.cpp │ ├── roundstat_serializer.cpp │ ├── sendcachedata.cpp │ ├── smartcontracts_serializer.cpp │ ├── staking.cpp │ ├── tokens_serializer.cpp │ ├── transactionsindex.cpp │ ├── transactionsiterator.cpp │ ├── transactionspacket.cpp │ ├── transactionsvalidator.cpp │ ├── walletscache.cpp │ ├── walletscache_serializer.cpp │ ├── walletsids.cpp │ ├── walletsids_serializer.cpp │ └── walletsstate.cpp ├── dbsql ├── CMakeLists.txt ├── include │ └── dbsql │ │ └── roundinfo.hpp └── src │ ├── pgbackend.cpp │ ├── pgbackend.h │ ├── pgconnection.cpp │ ├── pgconnection.h │ ├── roundinfo.cpp │ └── roundinfo.sql ├── example ├── config.ini ├── credits.node.systemd.service.in ├── hosts.txt └── new │ ├── PublicKey.txt │ ├── config.ini │ └── hosts.txt ├── js-client ├── api_test.html └── gen.sh ├── lib ├── CMakeLists.txt ├── include │ └── lib │ │ └── system │ │ ├── allocators.hpp │ │ ├── cache.hpp │ │ ├── common.hpp │ │ ├── concurrent.hpp │ │ ├── console.hpp │ │ ├── dynamicbuffer.hpp │ │ ├── fileutils.hpp │ │ ├── hash.hpp │ │ ├── lockfreechanger.hpp │ │ ├── logger.hpp │ │ ├── metastorage.hpp │ │ ├── mmappedfile.hpp │ │ ├── pmrfactory.hpp │ │ ├── process.hpp │ │ ├── processexception.hpp │ │ ├── progressbar.hpp │ │ ├── queues.hpp │ │ ├── random.hpp │ │ ├── reference.hpp │ │ ├── reflection.hpp │ │ ├── scopeguard.hpp │ │ ├── serialize_tuple.hpp │ │ ├── service │ │ ├── service.hpp │ │ ├── service_owner.hpp │ │ ├── unix_service.hpp │ │ ├── win_install.hpp │ │ └── win_service.hpp │ │ ├── shareable.hpp │ │ ├── signals.hpp │ │ ├── structures.hpp │ │ ├── timer.hpp │ │ └── utils.hpp └── src │ └── lib │ └── system │ ├── common.cpp │ ├── dynamicbuffer.cpp │ ├── logger.cpp │ ├── progressbar.cpp │ └── timer.cpp ├── lmdbxx ├── CMakeLists.txt ├── lmdb.cpp ├── lmdb.hpp ├── lmdb │ └── CMakeLists.txt └── lmdbexception.hpp ├── net ├── CMakeLists.txt ├── include │ └── net │ │ ├── logger.hpp │ │ ├── neighbourhood.hpp │ │ ├── networkcommands.hpp │ │ ├── packet.hpp │ │ ├── packetsqueue.hpp │ │ ├── packetvalidator.hpp │ │ └── transport.hpp └── src │ ├── neighbourhood.cpp │ ├── networkcommands.cpp │ ├── packet.cpp │ ├── packetsqueue.cpp │ ├── packetvalidator.cpp │ └── transport.cpp ├── samples ├── CMakeLists.txt └── api-client │ ├── CMakeLists.txt │ └── api-client.cpp ├── solver ├── CMakeLists.txt ├── include │ └── solver │ │ ├── callsqueuescheduler.hpp │ │ ├── consensus.hpp │ │ ├── inodestate.hpp │ │ ├── result.hpp │ │ ├── smartconsensus.hpp │ │ ├── smartcontracts.hpp │ │ ├── solvercontext.hpp │ │ ├── solvercore.hpp │ │ ├── stage.hpp │ │ ├── states │ │ ├── defaultstatebehavior.hpp │ │ ├── handlebbstate.hpp │ │ ├── handlertstate.hpp │ │ ├── normalstate.hpp │ │ ├── nostate.hpp │ │ ├── primitivewritestate.hpp │ │ ├── syncstate.hpp │ │ ├── trustedpoststagestate.hpp │ │ ├── trustedstage1state.hpp │ │ ├── trustedstage2state.hpp │ │ ├── trustedstage3state.hpp │ │ ├── waitingstate.hpp │ │ └── writingstate.hpp │ │ └── timeouttracking.hpp ├── src │ ├── callsqueuescheduler.cpp │ ├── consensus.cpp │ ├── smartconsensus.cpp │ ├── smartcontracts.cpp │ ├── solvercontext.cpp │ ├── solvercore.cpp │ ├── solverinterface.cpp │ ├── solvertransitions.cpp │ ├── stage.cpp │ ├── states │ │ ├── defaultstatebehavior.cpp │ │ ├── handlebbstate.cpp │ │ ├── handlertstate.cpp │ │ ├── normalstate.cpp │ │ ├── primitivewritestate.cpp │ │ ├── syncstate.cpp │ │ ├── trustedpoststagestate.cpp │ │ ├── trustedstage1state.cpp │ │ ├── trustedstage2state.cpp │ │ ├── trustedstage3state.cpp │ │ ├── waitingstate.cpp │ │ └── writingstate.cpp │ └── timeouttracking.cpp └── tests │ ├── CMakeLists.txt │ ├── mock │ ├── Solver │ │ ├── solver.hpp │ │ ├── transactionsvalidator.hpp │ │ └── walletsstate.hpp │ ├── blake2.hpp │ ├── callsqueuescheduler.hpp │ ├── csdb │ │ └── pool.hpp │ ├── csnode │ │ ├── blockchain.hpp │ │ ├── conveyer.hpp │ │ ├── csnode.hpp │ │ ├── transactionspacket.hpp │ │ └── walletscache.hpp │ ├── mockdata.hpp │ ├── sodium.hpp │ ├── solvercontext.hpp │ └── timeouttracking.hpp │ ├── test_trustedstage1state.cpp │ ├── test_trustedstage2state.cpp │ └── tests_main.cpp ├── tests ├── CMakeLists.txt ├── csnode │ ├── CMakeLists.txt │ ├── amount_tests.cpp │ ├── bitheap_tests.cpp │ ├── blockchain_tests.cpp │ ├── clientconfigmock.hpp │ ├── compressor_tests.cpp │ ├── conveyer_tests.cpp │ ├── cyclicbuffer_tests.cpp │ ├── datastream_tests.cpp │ ├── dynamicbuffer_tests.cpp │ ├── main.cpp │ ├── node_tests.cpp │ ├── nodemock.hpp │ ├── packetqueue_tests.cpp │ ├── pool_tests.cpp │ ├── poolcache_tests.cpp │ ├── poolsynchronizer_tests.cpp │ ├── smartcontractref_tests.cpp │ ├── smartcontracts_tests.cpp │ ├── solvermock.hpp │ ├── stage_tests.cpp │ ├── thrift_api_tests.cpp │ ├── transactionspacket_tests.cpp │ ├── transportmock.hpp │ ├── trxtail_tests.cpp │ └── validator_tests.cpp ├── lib_system │ ├── CMakeLists.txt │ ├── concurrent_tests.cpp │ ├── lib_system_tests.cpp │ ├── main.cpp │ ├── meta_storage_tests.cpp │ ├── process_tests.cpp │ ├── signals_tests.cpp │ └── timer_tests.cpp ├── lmdbxx │ ├── CMakeLists.txt │ ├── lmdb_tests.cpp │ └── main.cpp └── testprogram │ ├── CMakeLists.txt │ └── main.cpp └── third-party ├── CMakeLists.txt ├── lz4 ├── CMakeLists.txt ├── lz4.c └── lz4.h ├── patches ├── berkeley142_retargeting.patch ├── berkeleydb_141_17134_retargeting.patch ├── berkeleydb_141_17763_retargeting.patch ├── msvc142_retargeting.patch ├── msvs141_retargeting17134.patch └── msvs141_retargeting17763.patch └── rang ├── CMakeLists.txt ├── include └── rang │ └── rang.hpp └── rang.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | .dir-locals.el 3 | /.vs 4 | out/ 5 | /.vscode 6 | /local 7 | /CMakeSettings.json 8 | js-client/js/* 9 | .idea/ 10 | /CMakeLists.txt.user 11 | /vscbuild 12 | /CMakeLists.txt.user.4.10-pre1 13 | /build* 14 | *.swp 15 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third-party/googletest"] 2 | path = third-party/googletest 3 | url = https://github.com/google/googletest.git 4 | [submodule "third-party/berkeleydb"] 5 | path = third-party/berkeleydb 6 | url = https://github.com/CREDITSCOM/berkeleydb.git 7 | [submodule "third-party/thrift-interface-definitions"] 8 | path = third-party/thrift-interface-definitions 9 | url = https://github.com/CREDITSCOM/thrift-interface-definitions.git 10 | [submodule "third-party/thrift"] 11 | path = third-party/thrift 12 | url = https://github.com/CREDITSCOM/thrift.git 13 | [submodule "cscrypto"] 14 | path = cscrypto 15 | url = https://github.com/CREDITSCOM/cscrypto.git 16 | [submodule "third-party/lmdb"] 17 | path = third-party/lmdb 18 | url = https://github.com/LMDB/lmdb 19 | [submodule "third-party/lmdbxx"] 20 | path = third-party/lmdbxx 21 | url = https://github.com/drycpp/lmdbxx.git 22 | [submodule "third-party/nameof"] 23 | path = third-party/nameof 24 | url = https://github.com/Neargye/nameof.git 25 | [submodule "p2p"] 26 | path = p2p 27 | url = https://github.com/SychevS/p2p.git 28 | -------------------------------------------------------------------------------- /api/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | project(csconnector) 4 | 5 | # turn off optimization for this project in RelWithDebInfo only 6 | # configure_msvc_no_optimization() 7 | 8 | add_subdirectory(api_gen) 9 | add_subdirectory(executor_gen) 10 | add_subdirectory(variant_gen) 11 | 12 | # It's not recommended to use file(GLOB, because it's called only in the 13 | # Cmake-generator stage. When adding the files in the dir it won't be called - and the list of files 14 | # will not be updated. 15 | add_library(csconnector 16 | include/csstats.hpp 17 | src/csstats.cpp 18 | include/csconnector/csconnector.hpp 19 | src/csconnector.cpp 20 | src/apihandler.cpp 21 | include/apihandler.hpp 22 | include/debuglog.hpp 23 | include/tokens.hpp 24 | src/tokens.cpp 25 | include/profiler/profilerprocessor.hpp 26 | src/profilerprocessor.cpp 27 | include/profiler/profilereventhandler.hpp 28 | include/profiler/profiler.hpp 29 | src/profiler.cpp 30 | include/executormanager.hpp 31 | src/executormanager.cpp 32 | include/dumbcv.hpp 33 | src/dumbcv.cpp 34 | include/executor.hpp 35 | src/executor.cpp 36 | include/serializer.hpp 37 | include/apidiaghandler.hpp 38 | src/apidiaghandler.cpp 39 | ) 40 | 41 | target_link_libraries (csconnector PUBLIC csdb csnode lib csconnector_gen csconnector_executor_gen variant_gen) 42 | 43 | # INCLUDE DIRECTORIES it's better not to set globally but for each project. 44 | # INCLUDE DIRECTORIES consists of include libraries (in this case thrift and csdb) 45 | # and should not be set. Those are included into INTERFACE libs and will be included automatically 46 | # in target_link_libraries 47 | target_include_directories(csconnector 48 | PUBLIC include 49 | PRIVATE src 50 | ) 51 | 52 | configure_msvc_flags() 53 | 54 | set_property(TARGET csconnector PROPERTY CXX_STANDARD 17) 55 | set_property(TARGET csconnector PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 56 | -------------------------------------------------------------------------------- /api/executor_gen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | 3 | # It's better to put the files not into' ${CMAKE_CURRENT_SOURCE_DIR}, 4 | # ${CMAKE_CURRENT_BINARY_DIR}. But if in ${CMAKE_CURRENT_SOURCE_DIR}, 5 | # this dir should be added to .gitignore 6 | set(THRIFT_GEN_DIR ${CMAKE_CURRENT_BINARY_DIR}) 7 | 8 | # The files list is better to set in advance. IN the generation stage thirft compiler can't' 9 | # be built. In case of changes thrift-files-list should be 10 | # updated manually 11 | set(THRIFT_GENERATED_FILES 12 | ContractExecutor.cpp 13 | ContractExecutor.h 14 | executor_types.cpp 15 | executor_types.h 16 | executor_constants.cpp 17 | executor_constants.h 18 | ) 19 | 20 | # thrift compiler call is better to be added to build stage - in other cases 21 | # when thrift-file is changed it won't be compiled correctly. 22 | add_custom_command( 23 | OUTPUT ${THRIFT_GENERATED_FILES} 24 | COMMAND thrift-compiler -r -gen cpp:no_skeleton,pure_enums,moveable_types 25 | -out ${THRIFT_GEN_DIR} 26 | ${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/thrift-interface-definitions//executor.thrift 27 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/thrift-interface-definitions/executor.thrift 28 | ) 29 | 30 | add_library(csconnector_executor_gen 31 | ${THRIFT_GENERATED_FILES} 32 | ) 33 | 34 | target_link_libraries (csconnector_executor_gen PUBLIC thrift_static) 35 | target_include_directories(csconnector_executor_gen PUBLIC 36 | ${THRIFT_GEN_DIR}) 37 | 38 | set_property(TARGET csconnector_executor_gen PROPERTY CXX_STANDARD 14) 39 | set_property(TARGET csconnector_executor_gen PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 40 | -------------------------------------------------------------------------------- /api/include/apidiaghandler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef API_DIAG_HANDLER_HPP 2 | #define API_DIAG_HANDLER_HPP 3 | 4 | #include 5 | 6 | class Node; 7 | 8 | namespace api_diag { 9 | class APIDiagHandler : public API_DIAGNull { 10 | 11 | public: 12 | APIDiagHandler(Node& node); 13 | APIDiagHandler(const APIDiagHandler&) = delete; 14 | 15 | // former start node proto 16 | void GetActiveNodes(ActiveNodesResult& _return) override; 17 | void GetActiveTrustNodes(ActiveTrustNodesResult& _return) override; 18 | void GetActiveTransactionsCount(ActiveTransactionsResult& _return) override; 19 | void GetNodeStat(ActiveTrustNodesResult& _return, const general::Address& address) override; 20 | void GetNodeRewardEvaluation(RewardEvaluation& _return, const general::Address& address); 21 | // diagnostic proto 22 | void GetTransaction(GetTransactionResponse& _return, const TransactionId& id) override; 23 | 24 | void GetNodeInfo(NodeInfoRespone& _return, const NodeInfoRequest& request) override; 25 | 26 | void GetSupply(SupplyInfo& _return) override; 27 | 28 | void SetRawData(general::APIResponse& _return, const std::string& data) override; 29 | 30 | void UserCommand(general::APIResponse& _return, const std::string& data) override; 31 | 32 | private: 33 | Node& node_; 34 | }; 35 | 36 | // see: deprecated transport.cpp #1008 37 | constexpr int8_t platform() { 38 | #ifdef _WIN32 39 | return api_diag::Platform::OS_Windows; 40 | #elif __APPLE__ 41 | return api_diag::Platform::OS_MacOS; 42 | #else 43 | return api_diag::Platform::OS_Linux; 44 | #endif 45 | } 46 | 47 | } 48 | 49 | #endif // API_DIAG_HANDLER_HPP 50 | -------------------------------------------------------------------------------- /api/include/debuglog.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_LOG_HPP 2 | #define DEBUG_LOG_HPP 3 | 4 | #define DEBUG_LOG 5 | 6 | #ifdef DEBUG_LOG 7 | #include 8 | #endif 9 | 10 | #ifdef DEBUG_LOG 11 | 12 | inline void Log() { 13 | std::cerr << std::endl; 14 | } 15 | 16 | template 17 | inline void Log(T t, Args&&... args) { 18 | std::cerr << t; 19 | Log(args...); 20 | } 21 | 22 | #else 23 | 24 | template 25 | inline void Log(Args&&... args) { 26 | } 27 | 28 | #endif 29 | 30 | #ifdef NDEBUG 31 | template 32 | inline void DebugLog(T, Args&&...) { 33 | } 34 | #else 35 | template 36 | inline void DebugLog(T t, Args&&... args) { 37 | std::cerr << t; 38 | Log(args...); 39 | } 40 | #endif 41 | 42 | #endif // DEBUG_LOG_HPP 43 | -------------------------------------------------------------------------------- /api/include/dumbcv.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DUMBCV_HPP 2 | #define DUMBCV_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace cs { 10 | // for answer dumb transactions 11 | class DumbCv { 12 | const size_t kWaitTimeSec = 30;// 15 * 60; 13 | 14 | public: 15 | enum class Condition { 16 | Success, 17 | Rejected, 18 | TimeOut, 19 | Expired 20 | }; 21 | 22 | struct Result { 23 | cs::DumbCv::Condition condition; 24 | csdb::TransactionID id{}; 25 | csdb::Amount fee{}; 26 | }; 27 | 28 | bool addCVInfo(const cs::Signature& signature); 29 | void sendCvSignal(const cs::Signature& signature, Condition condition, const csdb::TransactionID& id, const csdb::Amount fee); 30 | DumbCv::Result waitCvSignal(const cs::Signature& signature); 31 | 32 | private: 33 | struct CvInfo { 34 | std::condition_variable cv; 35 | std::atomic_bool condFlg{ false }; 36 | std::atomic condition { Condition::Success }; 37 | csdb::TransactionID id{}; 38 | csdb::Amount fee{}; 39 | }; 40 | 41 | std::map cvInfo_; 42 | std::mutex mutex_; 43 | }; 44 | } 45 | 46 | #endif // DUMBCV_HPP 47 | -------------------------------------------------------------------------------- /api/include/executormanager.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EXECUTORMANAGER_HPP 2 | #define EXECUTORMANAGER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef _MSC_VER 9 | #pragma warning(push, 0) 10 | #endif 11 | 12 | #include 13 | 14 | #ifdef _MSC_VER 15 | #pragma warning(pop) 16 | #endif 17 | 18 | namespace cs { 19 | class ExecutorManager { 20 | public: 21 | using ProcessId = boost::process::pid_t; 22 | 23 | // returns true if executor exists at java processes 24 | bool isExecutorProcessRunning(ProcessId id) const; 25 | bool isExecutorProcessRunning() const; 26 | 27 | // returns all executor pids if executor exists at java processes 28 | std::optional> executorProcessIds() const; 29 | 30 | // stops executor 31 | bool stopExecutorProcess(ProcessId id); 32 | 33 | // stops all executor processes 34 | bool stopExecutorProcess(); 35 | 36 | private: 37 | std::string jpsData() const; 38 | void terminate(boost::process::pid_t pid); 39 | 40 | const std::string executorName_ = "contract-executor"; 41 | }; 42 | } 43 | 44 | #endif // EXECUTORMANAGER_HPP 45 | -------------------------------------------------------------------------------- /api/include/profiler/profilereventhandler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROFILEREVENTHANDLER_HPP 2 | #define PROFILEREVENTHANDLER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace cs { 11 | class ProfilerEventHandler : public apache::thrift::server::TServerEventHandler { 12 | public: 13 | virtual void processContext(void* serverContext, 14 | apache::thrift::stdcxx::shared_ptr transport) override { 15 | auto socket = static_cast<::apache::thrift::transport::TSocket *>(transport.get()); 16 | 17 | cs::ProfilerFileLogger::instance().add(socket->getSocketInfo()); 18 | apache::thrift::server::TServerEventHandler::processContext(serverContext, transport); 19 | } 20 | }; 21 | } 22 | 23 | #endif // PROFILEREVENTHANDLER_HPP 24 | 25 | -------------------------------------------------------------------------------- /api/include/profiler/profilerprocessor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROFILERPROCESSOR_HPP 2 | #define PROFILERPROCESSOR_HPP 3 | 4 | #include 5 | 6 | namespace cs { 7 | class ProfilerProcessor : public ::api::APIProcessor { 8 | public: 9 | explicit ProfilerProcessor(::apache::thrift::stdcxx::shared_ptr iface); 10 | virtual bool dispatchCall(::apache::thrift::protocol::TProtocol* iprot, 11 | ::apache::thrift::protocol::TProtocol* oprot, 12 | const std::string& fname, int32_t seqid, void* callContext) override; 13 | }; 14 | } 15 | 16 | #endif // PROFILERPROCESSOR_HPP 17 | -------------------------------------------------------------------------------- /api/include/serializer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SERIALIZER_HPP 2 | #define SERIALIZER_HPP 3 | 4 | #if defined(_MSC_VER) 5 | #pragma warning(push, 0) 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | #if defined(_MSC_VER) 12 | #pragma warning(pop) 13 | #endif 14 | 15 | #include 16 | 17 | namespace cs { 18 | class Serializer { 19 | public: 20 | template 21 | static T deserialize(std::string&& s) { 22 | using namespace ::apache; 23 | 24 | // https://stackoverflow.com/a/16261758/2016154 25 | static_assert(CHAR_BIT == 8 && std::is_same::value, "This code requires std::uint8_t to be implemented as unsigned char."); 26 | 27 | const auto buffer = thrift::stdcxx::make_shared(reinterpret_cast(&(s[0])), static_cast(s.size())); 28 | thrift::protocol::TBinaryProtocol proto(buffer); 29 | 30 | T sc; 31 | sc.read(&proto); 32 | 33 | return sc; 34 | } 35 | 36 | template 37 | static std::string serialize(const T& sc) { 38 | using namespace ::apache; 39 | 40 | auto buffer = thrift::stdcxx::make_shared(); 41 | thrift::protocol::TBinaryProtocol proto(buffer); 42 | sc.write(&proto); 43 | 44 | return buffer->getBufferAsString(); 45 | } 46 | }; 47 | } // namespace cs::api 48 | 49 | #endif // SERIALIZER_HPP 50 | -------------------------------------------------------------------------------- /api/include/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined(_MSC_VER) 18 | #pragma warning(push) 19 | // 4245: 'return': conversion from 'int' to 'SOCKET', signed/unsigned mismatch 20 | #pragma warning(disable: 4245 4706 4373) 21 | #endif // _MSC_VER 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #if defined(_MSC_VER) 29 | #pragma warning(pop) 30 | #endif // _MSC_VER 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #endif //STDAFX_H 37 | -------------------------------------------------------------------------------- /api/src/dumbcv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool cs::DumbCv::addCVInfo(const cs::Signature& signature) { 4 | cs::Lock lock(mutex_); 5 | 6 | if (const auto& it = cvInfo_.find(signature); it != cvInfo_.end()) { 7 | return false; 8 | } 9 | 10 | cvInfo_[signature]; 11 | return true; 12 | } 13 | 14 | void cs::DumbCv::sendCvSignal(const cs::Signature& signature, Condition condition, const csdb::TransactionID& id, const csdb::Amount fee) { 15 | cs::Lock lock(mutex_); 16 | 17 | if (auto it = cvInfo_.find(signature); it != cvInfo_.end()) { 18 | auto& [cv, flag, cond, i, f] = it->second; 19 | cond = condition; 20 | flag = true; 21 | i = id; 22 | f = fee; 23 | cv.notify_one(); 24 | } 25 | } 26 | 27 | cs::DumbCv::Result cs::DumbCv::waitCvSignal(const cs::Signature& signature) { 28 | Result result; 29 | result.condition = cs::DumbCv::Condition::TimeOut; 30 | 31 | std::unique_lock lock(mutex_); 32 | 33 | if (auto it = cvInfo_.find(signature); it != cvInfo_.end()) { 34 | it->second.cv.wait_for(lock, std::chrono::seconds(kWaitTimeSec), [it]() -> bool { 35 | return it->second.condFlg; 36 | }); 37 | 38 | if (it->second.condFlg) { 39 | result.condition = it->second.condition; 40 | result.id = it->second.id; 41 | result.fee = it->second.fee; 42 | } 43 | 44 | cvInfo_.erase(signature); 45 | } 46 | 47 | return result; 48 | } 49 | -------------------------------------------------------------------------------- /api/src/profiler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | cs::ProfilerFileLogger::~ProfilerFileLogger() { 9 | stop(); 10 | } 11 | 12 | void cs::ProfilerFileLogger::stop() { 13 | if (isRunning()) { 14 | isRunning_.store(false, std::memory_order_release); 15 | variable_.notify_all(); 16 | 17 | thread_.join(); 18 | } 19 | } 20 | 21 | void cs::ProfilerFileLogger::start() { 22 | if (!isRunning()) { 23 | isRunning_.store(true, std::memory_order_release); 24 | thread_ = std::thread(&cs::ProfilerFileLogger::eventLoop, this); 25 | } 26 | } 27 | 28 | bool cs::ProfilerFileLogger::isRunning() const { 29 | return isRunning_.load(std::memory_order_acquire); 30 | } 31 | 32 | void cs::ProfilerFileLogger::add(const std::string& message) { 33 | auto time = cs::Utils::formattedCurrentTime(cs::Utils::TimeFormat::DefaultMs); 34 | Data data { message, std::move(time) }; 35 | 36 | while (!queue_.push(data)); 37 | variable_.notify_one(); 38 | } 39 | 40 | cs::ProfilerFileLogger::ProfilerFileLogger(size_t size) 41 | : fileName_(path + "/" + fileName) 42 | , buffer_(size) 43 | , queue_(size) { 44 | if (!cs::FileUtils::createPathIfNoExist(path)) { 45 | std::cout << "Profiler file logger path creation failed\n"; 46 | } 47 | 48 | start(); 49 | } 50 | 51 | void cs::ProfilerFileLogger::eventLoop() { 52 | while (isRunning_.load(std::memory_order_acquire)) { 53 | std::unique_lock lock(mutex_); 54 | variable_.wait(lock, [this] { 55 | return queue_.read_available() || !isRunning(); 56 | }); 57 | 58 | while (queue_.read_available() != 0) { 59 | Data data; 60 | while (!queue_.pop(data)); 61 | 62 | buffer_.push_back(std::move(data)); 63 | } 64 | 65 | std::ofstream file(fileName_, std::ofstream::trunc); 66 | 67 | for (auto iter = buffer_.begin(); iter != buffer_.end(); ++iter) { 68 | auto length = static_cast(std::distance(iter, buffer_.end())); 69 | auto index = buffer_.size() - length; 70 | 71 | const Data& data = *iter; 72 | file << formatter(data.message, data.time, index) << "\n"; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /api/src/profilerprocessor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | cs::ProfilerProcessor::ProfilerProcessor(::apache::thrift::stdcxx::shared_ptr iface) 5 | : ::api::APIProcessor(iface) { 6 | } 7 | 8 | bool cs::ProfilerProcessor::dispatchCall(apache::thrift::protocol::TProtocol* iprot, 9 | apache::thrift::protocol::TProtocol* oprot, 10 | const std::string& fname, int32_t seqid, void* callContext) { 11 | cs::Profiler profiler("Method " + fname); 12 | return ::api::APIProcessor::dispatchCall(iprot, oprot, fname, seqid, callContext); 13 | } 14 | -------------------------------------------------------------------------------- /api/src/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" -------------------------------------------------------------------------------- /api/variant_gen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | 3 | # It's better to put the files not into' ${CMAKE_CURRENT_SOURCE_DIR}, 4 | # ${CMAKE_CURRENT_BINARY_DIR}. But if in ${CMAKE_CURRENT_SOURCE_DIR}, 5 | # this dir should be added to .gitignore 6 | set(THRIFT_GEN_DIR ${CMAKE_CURRENT_BINARY_DIR}) 7 | 8 | # The files list is better to set in advance. IN the generation stage thirft compiler can't' 9 | # be built. In case of changes thrift-files-list should be 10 | # updated manually 11 | set(THRIFT_GENERATED_FILES 12 | ${THRIFT_GEN_DIR}/general_constants.cpp 13 | ${THRIFT_GEN_DIR}/general_types.cpp 14 | ${THRIFT_GEN_DIR}/general_constants.h 15 | ${THRIFT_GEN_DIR}/general_types.h 16 | ) 17 | 18 | # thrift compiler call is better to be added to build stage - in other cases 19 | # when thrift-file is changed it won't be compiled correctly. 20 | add_custom_command( 21 | OUTPUT ${THRIFT_GENERATED_FILES} 22 | COMMAND thrift-compiler -r -gen cpp:no_skeleton,pure_enums,moveable_types 23 | -out ${THRIFT_GEN_DIR} 24 | ${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/thrift-interface-definitions/general.thrift 25 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../third-party/thrift-interface-definitions/general.thrift 26 | ) 27 | 28 | add_library(variant_gen 29 | ${THRIFT_GENERATED_FILES} 30 | variant_aux.cpp 31 | ) 32 | 33 | target_link_libraries (variant_gen PUBLIC thrift_static) 34 | target_include_directories(variant_gen PUBLIC 35 | ${THRIFT_GEN_DIR}) 36 | 37 | set_property(TARGET variant_gen PROPERTY CXX_STANDARD 14) 38 | set_property(TARGET variant_gen PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 39 | -------------------------------------------------------------------------------- /api/variant_gen/variant_aux.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace general { 5 | 6 | bool operator<(const _Variant__isset& a, const _Variant__isset& b) { 7 | auto ta = std::tie(a.v_boolean, a.v_double, a.v_short, a.v_int, a.v_long, a.v_byte, a.v_list, a.v_map, a.v_set, a.v_string); 8 | decltype(ta) tb = std::tie(b.v_boolean, b.v_double, b.v_short, b.v_int, b.v_long, b.v_byte, b.v_list, b.v_map, b.v_set, b.v_string); 9 | return ta < tb; 10 | } 11 | 12 | bool Variant::operator<(const Variant& that) const { 13 | const Variant &a = *this, &b = that; 14 | if (a.__isset < b.__isset) { 15 | return true; 16 | } 17 | if (b.__isset < a.__isset) { 18 | return false; 19 | } 20 | if (a.__isset.v_boolean) { 21 | return a.v_boolean < b.v_boolean; 22 | } 23 | if (a.__isset.v_double) { 24 | return a.v_double < b.v_double; 25 | } 26 | if (a.__isset.v_short) { 27 | return a.v_short < b.v_short; 28 | } 29 | if (a.__isset.v_int) { 30 | return a.v_int < b.v_int; 31 | } 32 | if (a.__isset.v_long) { 33 | return a.v_long < b.v_long; 34 | } 35 | if (a.__isset.v_byte) { 36 | return a.v_byte < b.v_byte; 37 | } 38 | if (a.__isset.v_string) { 39 | return a.v_string < b.v_string; 40 | } 41 | if (a.__isset.v_list) { 42 | return std::lexicographical_compare(a.v_list.begin(), a.v_list.end(), b.v_list.begin(), b.v_list.end()); 43 | } 44 | if (a.__isset.v_set) { 45 | return std::lexicographical_compare(a.v_set.begin(), a.v_set.end(), b.v_set.begin(), b.v_set.end()); 46 | } 47 | if (a.__isset.v_map) { 48 | return std::lexicographical_compare(a.v_map.begin(), a.v_map.end(), b.v_map.begin(), b.v_map.end()); 49 | } 50 | assert(false); 51 | return false; 52 | } 53 | } // namespace general 54 | -------------------------------------------------------------------------------- /benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(benchmark) 4 | 5 | # add new benches here 6 | add_subdirectory(testbench) 7 | add_subdirectory(lmdbbench) 8 | add_subdirectory(allocatorbench) 9 | add_subdirectory(signalsbench) 10 | 11 | set(CMAKE_CXX_STANDARD 17) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | configure_msvc_flags() 15 | 16 | add_library(${PROJECT_NAME} STATIC "./include/timeoutexception.hpp" 17 | "./include/benchmark.hpp" 18 | "./src/benchmark.cpp" 19 | "./include/framework.hpp") 20 | 21 | target_include_directories(${PROJECT_NAME} PUBLIC "./include") 22 | target_include_directories(${PROJECT_NAME} PUBLIC "./lmdbxx") 23 | target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../lib/include) 24 | 25 | target_link_libraries(${PROJECT_NAME} lmdbxx lib) 26 | -------------------------------------------------------------------------------- /benchmark/allocatorbench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(allocatorbench) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} "main.cpp") 9 | target_link_libraries(${PROJECT_NAME} benchmark) 10 | -------------------------------------------------------------------------------- /benchmark/allocatorbench/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cpp_lib_memory_resource 5 | #include 6 | #endif 7 | 8 | class A { 9 | public: 10 | char buffer[100] = {}; 11 | }; 12 | 13 | static constexpr size_t allocationsCount = 1000000; 14 | static std::vector storage; 15 | 16 | // default allocation 17 | static void defaultAllocation() { 18 | for (size_t i = 0; i < allocationsCount; ++i) { 19 | storage.push_back(new A{}); 20 | } 21 | 22 | for (A* a : storage) { 23 | delete a; 24 | } 25 | } 26 | 27 | static void testDefaultAllocation() { 28 | cs::Framework::execute(&defaultAllocation); 29 | storage.clear(); 30 | } 31 | 32 | #ifdef __cpp_lib_memory_resource 33 | static char resourceBuffer[sizeof(A) * allocationsCount]; 34 | static std::pmr::monotonic_buffer_resource resource{ resourceBuffer, sizeof(resourceBuffer), std::pmr::new_delete_resource() }; 35 | 36 | // memory source 37 | static void memorySourceAllocation() { 38 | for (size_t i = 0; i < allocationsCount; ++i) { 39 | storage.push_back(reinterpret_cast(resource.allocate(sizeof(A)))); 40 | } 41 | 42 | for (A* a : storage) { 43 | resource.deallocate(a, sizeof(A)); 44 | } 45 | } 46 | 47 | static void testMemorySourceAllocation() { 48 | cs::Framework::execute(&memorySourceAllocation); 49 | storage.clear(); 50 | } 51 | #endif 52 | 53 | int main() { 54 | storage.resize(allocationsCount); 55 | 56 | testDefaultAllocation(); 57 | #ifdef __cpp_lib_memory_resource 58 | testMemorySourceAllocation(); 59 | #endif 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /benchmark/include/framework.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FRAMEWORK_HPP 2 | #define FRAMEWORK_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace cs { 8 | class Framework { 9 | public: 10 | template > 11 | static Result execute(Func func, std::chrono::seconds max = std::chrono::seconds(30), [[maybe_unused]] const std::string& failedMessage = std::string{}) { 12 | try { 13 | if constexpr (std::is_same_v) { 14 | auto result = cs::Benchmark::run(func, max); 15 | 16 | if (!result) { 17 | cs::Console::writeLine("\n", failedMessage); 18 | cs::Console::writeLine("Failed running other tests, fix previous test to correct execution"); 19 | 20 | std::exit(0); 21 | } 22 | 23 | return result; 24 | } 25 | else if constexpr (std::is_same_v) { 26 | cs::Benchmark::run(func, max); 27 | } 28 | else { 29 | return cs::Benchmark::run(func, max); 30 | } 31 | } 32 | catch (const std::exception& e) { 33 | cs::Console::writeLine("Exception catched, message: ", e.what()); 34 | cs::Console::writeLine("Benchmark would be terminated"); 35 | 36 | std::terminate(); 37 | } 38 | } 39 | }; 40 | } // namespace cs 41 | 42 | #endif // FRAMEWORK_HPP 43 | 44 | -------------------------------------------------------------------------------- /benchmark/include/timeoutexception.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TIMEOUTEXCEPTION_HPP 2 | #define TIMEOUTEXCEPTION_HPP 3 | 4 | #include 5 | 6 | namespace cs { 7 | class TimeOutException : public std::exception { 8 | public: 9 | virtual const char* what() const noexcept override { 10 | return "Benchmark Time out"; 11 | } 12 | }; 13 | } 14 | 15 | #endif // TIMEOUTEXCEPTION_HPP 16 | -------------------------------------------------------------------------------- /benchmark/lmdbbench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(lmdbbench) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} "main.cpp") 9 | target_link_libraries(${PROJECT_NAME} benchmark) 10 | -------------------------------------------------------------------------------- /benchmark/lmdbbench/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | namespace fs = boost::filesystem; 6 | 7 | static void runBench(cs::Lmdb* db) { 8 | std::string key = "Key"; 9 | std::string value = "Value"; 10 | 11 | for (size_t i = 0; i < 10000; ++i) { 12 | db->insert(key + std::to_string(i), value); 13 | } 14 | } 15 | 16 | static void testLmdb(unsigned int flags) { 17 | const char* path = "testdbpath"; 18 | 19 | cs::Lmdb db(path); 20 | db.open(flags); 21 | 22 | cs::Framework::execute(std::bind(&runBench, &db), std::chrono::seconds(100), "Db run failed"); 23 | 24 | db.close(); 25 | fs::remove_all(fs::path(path)); 26 | } 27 | 28 | static void testLmdbDefaultFlags() { 29 | testLmdb(lmdb::env::default_flags); 30 | } 31 | 32 | static void testLmdbWithFlags() { 33 | testLmdb(MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC); 34 | } 35 | 36 | int main() { 37 | testLmdbDefaultFlags(); 38 | testLmdbWithFlags(); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /benchmark/signalsbench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(signalsbench) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} "main.cpp") 9 | target_link_libraries(${PROJECT_NAME} benchmark) 10 | -------------------------------------------------------------------------------- /benchmark/src/benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /benchmark/testbench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(testbench) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | add_library(${PROJECT_NAME} STATIC "instance.hpp" "instance.cpp") 9 | target_link_libraries(${PROJECT_NAME} benchmark) 10 | -------------------------------------------------------------------------------- /benchmark/testbench/instance.cpp: -------------------------------------------------------------------------------- 1 | #include "instance.hpp" 2 | 3 | void voidTest() { 4 | } 5 | 6 | bool boolTest() { 7 | return true; 8 | } 9 | 10 | std::vector vectorTest() { 11 | return std::vector{}; 12 | } 13 | 14 | cstests::TestBenchmarkInstance::TestBenchmarkInstance() { 15 | cs::Framework::execute(&voidTest); 16 | cs::Framework::execute(&boolTest); 17 | cs::Framework::execute(&vectorTest); 18 | } 19 | 20 | static cstests::TestBenchmarkInstance value{}; 21 | -------------------------------------------------------------------------------- /benchmark/testbench/instance.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_INSTANCE_HPP 2 | #define TEST_INSTANCE_HPP 3 | 4 | #include 5 | 6 | namespace cstests { 7 | class TestBenchmarkInstance { 8 | public: 9 | explicit TestBenchmarkInstance(); 10 | }; 11 | } 12 | 13 | #endif // TEST_INSTANCE_HPP 14 | -------------------------------------------------------------------------------- /client/config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 5 | 6 | project(config) 7 | 8 | add_library(${PROJECT_NAME} 9 | "observer.hpp" 10 | "observer.cpp" 11 | "config.hpp" 12 | "config.cpp" 13 | ) 14 | 15 | target_link_libraries (${PROJECT_NAME} csnode lib) 16 | 17 | target_include_directories(client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/client 18 | ${CMAKE_CURRENT_SOURCE_DIR}/../lib/include) 19 | 20 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) 21 | set_property(TARGET ${PROJECT_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 22 | 23 | suppress_boost_cmake_warnings() 24 | configure_msvc_flags() 25 | 26 | set (Boost_USE_MULTITHREADED ON) 27 | set (Boost_USE_STATIC_LIBS ON) 28 | if(NOT APPLE) 29 | set (Boost_USE_STATIC_RUNTIME ON) 30 | endif() 31 | 32 | find_package (Threads) 33 | find_package (Boost REQUIRED COMPONENTS system filesystem program_options date_time regex) 34 | target_link_libraries (${PROJECT_NAME} 35 | Boost::system 36 | Boost::filesystem 37 | Boost::program_options 38 | Boost::date_time 39 | Boost::regex 40 | Boost::disable_autolinking 41 | ${CMAKE_THREAD_LIBS_INIT} 42 | ) 43 | 44 | if (NOT MSVC AND WITH_GPROF) 45 | add_definitions(-DBUILD_WITH_GPROF) 46 | target_link_libraries (${PROJECT_NAME} dl) 47 | endif() 48 | -------------------------------------------------------------------------------- /client/config/observer.cpp: -------------------------------------------------------------------------------- 1 | #include "observer.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | cs::config::Observer::Observer(Config& config, boost::program_options::variables_map& map) 8 | : config_(config) 9 | , map_(map) 10 | , publicKey_(config.getMyPublicKey()) 11 | , privateKey_(config.getMyPrivateKey()) { 12 | thread_ = std::thread(&Observer::eventLoop, this); 13 | } 14 | 15 | cs::config::Observer::~Observer() { 16 | stop(); 17 | } 18 | 19 | void cs::config::Observer::stop() { 20 | if (isObserved_.load(std::memory_order_acquire)) { 21 | isObserved_.store(false, std::memory_order_release); 22 | variable_.notify_one(); 23 | 24 | thread_.join(); 25 | } 26 | } 27 | 28 | bool cs::config::Observer::isObserved() const { 29 | return isObserved_.load(std::memory_order_acquire); 30 | } 31 | 32 | void cs::config::Observer::notify() { 33 | if (isObserved()) { 34 | variable_.notify_one(); 35 | } 36 | } 37 | 38 | void cs::config::Observer::eventLoop() { 39 | isObserved_.store(true, std::memory_order_release); 40 | 41 | std::unique_lock lock(mutex_); 42 | 43 | while (isObserved_.load(std::memory_order_acquire)) { 44 | variable_.wait_for(lock, std::chrono::milliseconds(config_.observerWaitTime())); 45 | 46 | if (!isObserved_.load(std::memory_order_acquire)) { 47 | break; 48 | } 49 | 50 | Config config = Config::read(map_, false); 51 | 52 | if (config.isGood()) { 53 | config.publicKey_ = publicKey_; 54 | config.privateKey_ = privateKey_; 55 | 56 | if (config_ != config) { 57 | emit configChanged(config, config_); 58 | config_ = std::move(config); 59 | } 60 | } 61 | else { 62 | cswarning() << "config.ini can not be read by observer, check config.ini format or file existing"; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /client/config/observer.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | class Config; 12 | 13 | namespace cs::config { 14 | using ConfigChangeSignal = cs::Signal; 15 | 16 | class Observer { 17 | public: 18 | explicit Observer(Config& config, boost::program_options::variables_map& map); 19 | ~Observer(); 20 | 21 | void stop(); 22 | bool isObserved() const; 23 | 24 | void notify(); 25 | 26 | public signals: 27 | // generates when new config updated 28 | // called from another thread 29 | ConfigChangeSignal configChanged; 30 | 31 | private: 32 | void eventLoop(); 33 | 34 | Config& config_; 35 | boost::program_options::variables_map& map_; 36 | 37 | cs::PublicKey publicKey_{}; 38 | cs::PrivateKey privateKey_{}; 39 | 40 | std::atomic isObserved_ = { false }; 41 | std::mutex mutex_; 42 | std::condition_variable variable_; 43 | std::thread thread_; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /client/include/client/cmdlineargs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct cmdline { 4 | static constexpr const char* argHelp = "help"; 5 | static constexpr const char* argVersion = "version"; 6 | static constexpr const char* argDBPath = "db-path"; 7 | static constexpr const char* argSeed = "seed"; 8 | static constexpr const char* argDumpKeys = "dumpkeys"; 9 | static constexpr const char* argSetBCTop = "set-bc-top"; 10 | static constexpr const char* argBalChange = "bal-change"; 11 | #ifdef _WIN32 12 | static constexpr const char* argInstall = "install"; 13 | static constexpr const char* argUninstall = "uninstall"; 14 | #endif 15 | static constexpr const char* argWorkDir = "working_dir"; 16 | }; 17 | -------------------------------------------------------------------------------- /client/include/client/params.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PARAMS_HPP 2 | #define PARAMS_HPP 3 | 4 | /** 5 | * Please don't commit these three defines 6 | * below uncommented. 7 | */ 8 | //#define MONITOR_NODE 9 | //#define WEB_WALLET_NODE 10 | 11 | #define NODE_API 12 | #define AJAX_IFACE 13 | 14 | #define AJAX_CONCURRENT_API_CLIENTS INT64_MAX 15 | #define BINARY_TCP_API 16 | #define BINARY_TCP_EXECAPI 17 | #define DEFAULT_CURRENCY 1 18 | 19 | #if defined(MONITOR_NODE) || defined(WEB_WALLET_NODE) 20 | #define PROFILE_API 21 | #define TOKENS_CACHE 22 | #endif 23 | 24 | #ifdef MONITOR_NODE 25 | #define STATS 26 | #endif 27 | 28 | // diagnostic output & compatibility checks 29 | #if defined(_MSC_VER) 30 | 31 | #if defined(MONITOR_NODE) 32 | 33 | #if defined(WEB_WALLET_NODE) 34 | #error Incompatible macros defined: MONITOR_NODE & WEB_WALLET_NODE 35 | #endif 36 | //#pragma message ( "*** Building monitor node" ) 37 | 38 | #elif defined(WEB_WALLET_NODE) 39 | 40 | #if defined(MONITOR_NODE) 41 | #error Incompatible macros defined: WEB_WALLET_NODE & MONITOR_NODE 42 | #endif 43 | //#pragma message ( "*** Building web wallet node" ) 44 | 45 | #else 46 | 47 | //#pragma message ( "*** Building basic node" ) 48 | 49 | #endif 50 | 51 | #endif // _MSC_VER 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /client/include/client/peer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifndef WIN32_LEAN_AND_MEAN 6 | #define WIN32_LEAN_AND_MEAN 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace cs { 17 | 18 | class Peer : public ServiceOwner { 19 | public: 20 | Peer( 21 | const char* serviceName, 22 | Config&, 23 | boost::program_options::variables_map& 24 | ); 25 | int executeProtocol(); 26 | 27 | protected: 28 | // ServiceOwner interface 29 | bool onInit(const char* serviceName) override; 30 | bool onRun(const char* serviceName) override; 31 | bool onStop() override; 32 | bool onPause() override; 33 | bool onContinue() override; 34 | #ifndef _WIN32 35 | bool onFork(const char*, pid_t) override; 36 | #endif 37 | 38 | private: 39 | Service service_; 40 | std::unique_ptr node_; 41 | std::unique_ptr observer_; 42 | Config& config_; 43 | boost::program_options::variables_map& vm_; 44 | }; 45 | 46 | } // namespace cs 47 | -------------------------------------------------------------------------------- /client/include/client/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include -------------------------------------------------------------------------------- /client/include/client/version.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace client { 6 | struct Version { 7 | static const std::string GIT_SHA1; 8 | static const std::string GIT_DATE; 9 | static const std::string GIT_COMMIT_SUBJECT; 10 | }; 11 | } // namespace clinet 12 | -------------------------------------------------------------------------------- /client/src/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" -------------------------------------------------------------------------------- /client/src/version.cpp.in: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace client; 4 | 5 | const std::string Version::GIT_SHA1 = "@GIT_SHA1@"; 6 | const std::string Version::GIT_DATE = "@GIT_DATE@"; 7 | const std::string Version::GIT_COMMIT_SUBJECT = "@GIT_COMMIT_SUBJECT@"; 8 | -------------------------------------------------------------------------------- /csdb/benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | project(csdb_benchmark) 4 | 5 | include(ExternalProject) 6 | 7 | ExternalProject_Add(googlebenchmark 8 | GIT_REPOSITORY https://github.com/google/benchmark.git 9 | UPDATE_DISCONNECTED 1 10 | CMAKE_ARGS 11 | -DCMAKE_BUILD_TYPE=$ 12 | -DBENCHMARK_ENABLE_TESTING=OFF 13 | PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gbench" 14 | INSTALL_COMMAND "" 15 | ) 16 | 17 | ExternalProject_Get_Property(googlebenchmark SOURCE_DIR) 18 | set(GBENCH_INCLUDE_DIRS ${SOURCE_DIR}/include) 19 | include_directories(${GBENCH_INCLUDE_DIRS}) 20 | 21 | ExternalProject_Get_Property(googlebenchmark BINARY_DIR) 22 | set(GBENCH_LIBS_DIR ${BINARY_DIR}/src) 23 | 24 | set(CSDB_INCLUDE_DIRS ../include) 25 | set(CSDB_SOURCE_DIR ../src) 26 | 27 | add_executable(${PROJECT_NAME} 28 | csdb_benchmark_main.cpp 29 | ) 30 | set_target_properties(${PROJECT_NAME} PROPERTIES 31 | CXX_STANDARD 11 32 | CXX_STANDARD_REQUIRED ON 33 | ) 34 | add_dependencies(${PROJECT_NAME} googlebenchmark) 35 | target_compile_definitions(${PROJECT_NAME} 36 | PRIVATE -DCSDB_BENCHMARK 37 | ) 38 | 39 | target_include_directories(${PROJECT_NAME} PUBLIC ${CSDB_INCLUDE_DIRS}) 40 | target_link_libraries(${PROJECT_NAME} leveldb) 41 | target_link_libraries(${PROJECT_NAME} 42 | ${GBENCH_LIBS_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX} 43 | ) 44 | if(UNIX) 45 | target_link_libraries(${PROJECT_NAME} pthread) 46 | endif() 47 | 48 | if (WIN32) 49 | target_link_libraries(${PROJECT_NAME} Shlwapi) 50 | endif() 51 | -------------------------------------------------------------------------------- /csdb/benchmark/csdb_benchmark_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void bench(benchmark::State &state) 4 | { 5 | for(auto _ : state) 6 | { 7 | } 8 | } 9 | BENCHMARK(bench); 10 | 11 | BENCHMARK_MAIN(); 12 | -------------------------------------------------------------------------------- /csdb/include/csdb/csdb.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file csdb.h 3 | * @author Evgeny V. Zalivochkin 4 | */ 5 | 6 | #ifndef _CREDITS_CSDB_H_INCLUDED_ 7 | #define _CREDITS_CSDB_H_INCLUDED_ 8 | 9 | #include 10 | 11 | namespace csdb { 12 | /* The global functions set is necessary for the compatibility with previous csdb version, 13 | * and for working with the single storage without creating \ref ::csdb::Storage class object. 14 | * 15 | * This set almost copies the method's det of \ref ::csdb::Storage, realizing the work with single 16 | * internal class object. The detailed description of methods is in the \ref ::csdb::Storage 17 | * class documentation. 18 | */ 19 | 20 | /** 21 | * @brief Initializing of inner storage object 22 | * 23 | * The method parameters are equivalent to those of \ref ::csdb::Storage::open, main discrepancy is 24 | * that, in the case when inner \ref ::csdb::Storage object is already opened, then method doesn't 25 | * try to open the new Storage, but returns false immediately. 26 | * 27 | * @sa ::csdb::Storage::open 28 | */ 29 | bool init(const Storage::OpenOptions& options, Storage::OpenCallback callback = nullptr); 30 | 31 | /** 32 | * @overload 33 | */ 34 | bool init(const char* path_to_bases, const Storage::OpenCallback& callback = nullptr); 35 | 36 | /** 37 | * @brief 38 | Check if the internal storage object is initialized 39 | * @sa ::csdb::Storage::isOpen 40 | */ 41 | bool isInitialized(); 42 | 43 | /** 44 | * @brief Closing of internal storage object 45 | * @sa ::csdb::Storage::close 46 | */ 47 | void done(); 48 | 49 | /** 50 | * @brief Last error code 51 | * @sa ::csdb::Storage::last_error() 52 | */ 53 | Storage::Error lastError(); 54 | 55 | /** 56 | * @brief Last error description 57 | * @sa ::csdb::Storage::last_error_message() 58 | */ 59 | ::std::string lastErrorMessage(); 60 | 61 | /** 62 | * @brief Last database drivers work error code 63 | * @sa ::csdb::Storage::db_last_error() 64 | */ 65 | Database::Error dbLastError(); 66 | 67 | /** 68 | * @brief Last database drivers work error description 69 | * @sa ::csdb::Storage::db_last_error_message() 70 | */ 71 | ::std::string dbLastErrorMessage(); 72 | 73 | /** 74 | * @brief Default storage 75 | * @return Internal object of storage 76 | */ 77 | Storage defaultStorage(); 78 | 79 | } // namespace csdb 80 | 81 | #endif // _CREDITS_CSDB_H_INCLUDED_ 82 | -------------------------------------------------------------------------------- /csdb/include/csdb/currency.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file currency.h 3 | * @author Evgeny V. Zalivochkin 4 | */ 5 | 6 | #ifndef _CREDITS_CSDB_CURRENCY_H_INCLUDED_ 7 | #define _CREDITS_CSDB_CURRENCY_H_INCLUDED_ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace csdb { 16 | 17 | namespace priv { 18 | class obstream; 19 | class ibstream; 20 | } // namespace priv 21 | 22 | class Currency { 23 | SHARED_DATA_CLASS_DECLARE(Currency) 24 | public: 25 | Currency(const uint8_t& id); 26 | 27 | bool is_valid() const noexcept; 28 | std::string to_string() const noexcept; 29 | 30 | bool operator==(const Currency& other) const noexcept; 31 | bool operator!=(const Currency& other) const noexcept; 32 | bool operator<(const Currency& other) const noexcept; 33 | 34 | private: 35 | void put(::csdb::priv::obstream&) const; 36 | bool get(::csdb::priv::ibstream&); 37 | friend class ::csdb::priv::obstream; 38 | friend class ::csdb::priv::ibstream; 39 | }; 40 | 41 | class Currency::priv : public ::csdb::internal::shared_data { 42 | public: 43 | uint8_t id = 0; 44 | DEFAULT_PRIV_CLONE() 45 | }; 46 | SHARED_DATA_CLASS_IMPLEMENTATION_INLINE(Currency) 47 | 48 | typedef std::vector CurrencyList; 49 | 50 | } // namespace csdb 51 | 52 | #endif // _CREDITS_CSDB_CURRENCY_H_INCLUDED_ 53 | -------------------------------------------------------------------------------- /csdb/include/csdb/database_berkeleydb.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file database_berkeleydb.h 3 | * @author Evgeny Zalivochkin 4 | */ 5 | 6 | #ifndef _CREDITS_CSDB_DATABASE_BERKELEY_H_INCLUDED_ 7 | #define _CREDITS_CSDB_DATABASE_BERKELEY_H_INCLUDED_ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace berkeleydb { 16 | class DB; 17 | class Status; 18 | struct Options; 19 | } // namespace berkeleydb 20 | 21 | namespace csdb { 22 | 23 | class DatabaseBerkeleyDB : public Database { 24 | public: 25 | DatabaseBerkeleyDB(); 26 | ~DatabaseBerkeleyDB() override; 27 | 28 | public: 29 | bool open(const std::string& path); 30 | 31 | private: 32 | bool is_open() const final; 33 | bool put(const cs::Bytes& key, uint32_t seq_no, const cs::Bytes& value) final; 34 | bool get(const cs::Bytes& key, cs::Bytes* value) final; 35 | bool get(const uint32_t seq_no, cs::Bytes* value) final; 36 | bool remove(const cs::Bytes&) final; 37 | bool seq_no(const cs::Bytes& key, uint32_t* value) final; // sequence from block hash 38 | bool write_batch(const ItemList&) final; 39 | IteratorPtr new_iterator() final; 40 | 41 | bool updateContractData(const cs::Bytes& key, const cs::Bytes& data) override; 42 | bool getContractData(const cs::Bytes& key, cs::Bytes& data) override; 43 | 44 | void logfile_routine(); 45 | 46 | private: 47 | class Iterator; 48 | 49 | private: 50 | void set_last_error_from_berkeleydb(int status); 51 | 52 | private: 53 | DbEnv env_; 54 | std::unique_ptr db_blocks_; 55 | std::unique_ptr db_seq_no_; 56 | std::unique_ptr db_contracts_; 57 | std::thread logfile_thread_; 58 | bool quit_ = false; 59 | }; 60 | 61 | } // namespace csdb 62 | #endif // _CREDITS_CSDB_DATABASE_BERKELEYDB_H_INCLUDED_ 63 | -------------------------------------------------------------------------------- /csdb/include/csdb/internal/types.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file types.h 3 | * @author Roman Bukin 4 | */ 5 | 6 | #ifndef _CREDITS_CSDB_TYPES_H_INCLUDED_ 7 | #define _CREDITS_CSDB_TYPES_H_INCLUDED_ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | namespace csdb { 16 | namespace internal { 17 | 18 | using WalletId = uint32_t; 19 | 20 | } // namespace internal 21 | } // namespace csdb 22 | 23 | #endif // _CREDITS_CSDB_TYPES_H_INCLUDED_ 24 | -------------------------------------------------------------------------------- /csdb/include/csdb/wallet.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file wallet.h 3 | * @author Roman Bukin 4 | */ 5 | 6 | #ifndef _CREDITS_CSDB_WALLET_H_INCLUDED_ 7 | #define _CREDITS_CSDB_WALLET_H_INCLUDED_ 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace csdb { 18 | 19 | class Address; 20 | class Amount; 21 | class Storage; 22 | 23 | class Wallet { 24 | SHARED_DATA_CLASS_DECLARE(Wallet) 25 | 26 | public: 27 | static Wallet get(Address address, Storage storage = Storage()); 28 | 29 | bool is_valid() const noexcept; 30 | Address address() const noexcept; 31 | 32 | CurrencyList currencies() const noexcept; 33 | Amount amount(Currency currency) const noexcept; 34 | }; 35 | 36 | class Wallet::priv : public ::csdb::internal::shared_data { 37 | priv() = default; 38 | 39 | explicit priv(Address address) 40 | : address_(address) { 41 | } 42 | 43 | Address address_; 44 | std::map amounts_; 45 | 46 | priv clone() const { 47 | priv result; 48 | 49 | result.address_ = address_.clone(); 50 | 51 | for (auto &am : amounts_) 52 | result.amounts_[am.first.clone()] = am.second; 53 | 54 | return result; 55 | } 56 | 57 | friend class Wallet; 58 | }; 59 | SHARED_DATA_CLASS_IMPLEMENTATION_INLINE(Wallet) 60 | 61 | } // namespace csdb 62 | 63 | #endif // _CREDITS_CSDB_WALLET_H_INCLUDED_ 64 | -------------------------------------------------------------------------------- /csdb/src/amount_commission.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "binary_streams.hpp" 6 | 7 | namespace csdb { 8 | 9 | AmountCommission::AmountCommission(uint16_t value) { 10 | u_.bits = value; 11 | } 12 | 13 | AmountCommission::AmountCommission(double value) { 14 | u_.fIEEE.sign = value < 0. ? 1 : 0; 15 | value = std::fabs(value); 16 | double expf = value == 0. ? 0. : std::log10(value); 17 | int expi = static_cast(expf >= 0. ? expf + 0.5 : expf - 0.5); 18 | value /= std::pow(10, expi); 19 | if (value >= 1.) { 20 | value *= 0.1; 21 | ++expi; 22 | } 23 | u_.fIEEE.exp = static_cast(expi + 18); 24 | u_.fIEEE.frac = static_cast(lround(value * 1024)); 25 | } 26 | 27 | void AmountCommission::put(priv::obstream& os) const { 28 | os.put(u_.bits); 29 | } 30 | 31 | bool AmountCommission::get(priv::ibstream& is) { 32 | cached_.store(false, std::memory_order_relaxed); 33 | return is.get(u_.bits); 34 | } 35 | 36 | } // namespace csdb 37 | -------------------------------------------------------------------------------- /csdb/src/binary_streams.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "binary_streams.hpp" 4 | #include "integral_encdec.hpp" 5 | 6 | namespace csdb { 7 | namespace priv { 8 | 9 | void obstream::put(const void *buf, size_t size) { 10 | auto data = static_cast(buf); 11 | buffer_.insert(buffer_.end(), data, data + size); 12 | } 13 | 14 | void obstream::put(const std::string &value) { 15 | put(static_cast(value.size())); 16 | buffer_.insert(buffer_.end(), value.begin(), value.end()); 17 | } 18 | 19 | void obstream::put(const cs::Bytes &value) { 20 | put(value.size()); 21 | buffer_.insert(buffer_.end(), value.begin(), value.end()); 22 | } 23 | 24 | bool ibstream::get(void *buf, size_t size) { 25 | if (size > size_) { 26 | return false; 27 | } 28 | 29 | auto src = static_cast(data_); 30 | std::memmove(buf, src, size); 31 | size_ -= size; 32 | data_ = static_cast(src + size); 33 | return true; 34 | } 35 | 36 | bool ibstream::get(std::string &value) { 37 | uint32_t size; 38 | if (!get(size)) { 39 | return false; 40 | } 41 | if (size > size_) { 42 | return false; 43 | } 44 | 45 | auto data = static_cast(data_); 46 | value.assign(data, size); 47 | size_ -= size; 48 | data_ = static_cast(data + size); 49 | return true; 50 | } 51 | 52 | bool ibstream::get(cs::Bytes &value) { 53 | size_t size; 54 | if (!get(size)) { 55 | return false; 56 | } 57 | if (size > size_) { 58 | return false; 59 | } 60 | 61 | const auto data = static_cast(data_); 62 | value.assign(data, data + size); 63 | size_ -= size; 64 | data_ = static_cast(data + size); 65 | return true; 66 | } 67 | 68 | } // namespace priv 69 | } // namespace csdb 70 | -------------------------------------------------------------------------------- /csdb/src/csdb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace csdb { 4 | 5 | namespace { 6 | ::csdb::Storage instance; 7 | } // namespace 8 | 9 | bool init(const Storage::OpenOptions& options, Storage::OpenCallback callback) { 10 | if (instance.isOpen()) { 11 | return false; 12 | } 13 | instance = ::csdb::Storage::get(options, std::move(callback)); 14 | return instance.isOpen(); 15 | } 16 | 17 | bool init(const char* path_to_bases, Storage::OpenCallback callback) { 18 | if (instance.isOpen()) { 19 | return false; 20 | } 21 | instance = ::csdb::Storage::get(path_to_bases, std::move(callback)); 22 | return instance.isOpen(); 23 | } 24 | 25 | bool isInitialized() { 26 | return instance.isOpen(); 27 | } 28 | 29 | void done() { 30 | instance.close(); 31 | } 32 | 33 | Storage::Error lastError() { 34 | return instance.last_error(); 35 | } 36 | 37 | ::std::string lastErrorMessage() { 38 | return instance.last_error_message(); 39 | } 40 | 41 | Database::Error dbLastError() { 42 | return instance.db_last_error(); 43 | } 44 | 45 | ::std::string dbLastErrorMessage() { 46 | return instance.last_error_message(); 47 | } 48 | 49 | Storage defaultStorage() { 50 | return instance; 51 | } 52 | 53 | } // namespace csdb 54 | -------------------------------------------------------------------------------- /csdb/src/currency.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "binary_streams.hpp" 4 | 5 | namespace csdb { 6 | 7 | Currency::Currency(const uint8_t &id) 8 | : Currency() { 9 | d->id = id; 10 | } 11 | 12 | bool Currency::is_valid() const noexcept { 13 | return d != nullptr; 14 | } 15 | 16 | std::string Currency::to_string() const noexcept { 17 | return std::to_string(d->id); 18 | } 19 | 20 | bool Currency::operator==(const Currency &other) const noexcept { 21 | return d->id == other.d->id; 22 | } 23 | 24 | bool Currency::operator!=(const Currency &other) const noexcept { 25 | return !operator==(other); 26 | } 27 | 28 | bool Currency::operator<(const Currency &other) const noexcept { 29 | return d->id < other.d->id; 30 | } 31 | 32 | void Currency::put(::csdb::priv::obstream &os) const { 33 | os.put(d->id); 34 | } 35 | 36 | bool Currency::get(::csdb::priv::ibstream &is) { 37 | return is.get(d->id); 38 | } 39 | 40 | } // namespace csdb 41 | -------------------------------------------------------------------------------- /csdb/src/priv_crypto.cpp: -------------------------------------------------------------------------------- 1 | #include "priv_crypto.hpp" 2 | 3 | #ifdef CSDB_UNIT_TEST 4 | #include 5 | #endif 6 | 7 | namespace csdb { 8 | namespace priv { 9 | 10 | cs::Bytes crypto::calc_hash(const cs::Bytes &buffer) noexcept { 11 | #ifndef CSDB_UNIT_TEST 12 | cscrypto::Hash result = cscrypto::calculateHash(buffer.data(), buffer.size()); 13 | return cs::Bytes(result.begin(), result.end()); 14 | #else 15 | const size_t result = std::hash()(std::string(buffer.begin(), buffer.end())); 16 | return cs::Bytes(reinterpret_cast(&result), reinterpret_cast(&result) + hash_size); 17 | #endif 18 | } 19 | 20 | } // namespace priv 21 | } // namespace csdb 22 | -------------------------------------------------------------------------------- /csdb/src/priv_crypto.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file priv_crypto.h 3 | * @author Roman Bukin 4 | */ 5 | 6 | #ifndef _CREDITS_CSDB_PRIVATE_CRYPTO_H_H_INCLUDED_ 7 | #define _CREDITS_CSDB_PRIVATE_CRYPTO_H_H_INCLUDED_ 8 | 9 | #include 10 | 11 | #include 12 | 13 | #ifndef CSDB_UNIT_TEST 14 | #include "cscrypto/cscrypto.hpp" 15 | #endif 16 | 17 | namespace csdb { 18 | namespace priv { 19 | 20 | struct crypto { 21 | #ifndef CSDB_UNIT_TEST 22 | static const size_t hash_size = cscrypto::kHashSize; 23 | static const size_t public_key_size = cscrypto::kPublicKeySize; 24 | #else 25 | static const size_t hash_size = sizeof(size_t); 26 | static const size_t public_key_size = 20; 27 | #endif 28 | static cs::Bytes calc_hash(const cs::Bytes &buffer) noexcept; 29 | }; 30 | 31 | } // namespace priv 32 | } // namespace csdb 33 | 34 | #endif // _CREDITS_CSDB_PRIVATE_CRYPTO_H_H_INCLUDED_ 35 | -------------------------------------------------------------------------------- /csdb/src/wallet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace csdb { 10 | 11 | bool Wallet::is_valid() const noexcept { 12 | return d->address_.is_valid(); 13 | } 14 | 15 | Address Wallet::address() const noexcept { 16 | return d->address_; 17 | } 18 | 19 | CurrencyList Wallet::currencies() const noexcept { 20 | CurrencyList res; 21 | res.reserve(d->amounts_.size()); 22 | 23 | for (const auto &it : d->amounts_) { 24 | res.push_back(it.first); 25 | } 26 | 27 | return res; 28 | } 29 | 30 | Amount Wallet::amount(Currency currency) const noexcept { 31 | const auto it = d->amounts_.find(currency); 32 | return (it != d->amounts_.end()) ? it->second : 0_c; 33 | } 34 | 35 | Wallet Wallet::get(Address address, Storage storage) { 36 | if (!storage.isOpen()) { 37 | storage = csdb::defaultStorage(); 38 | if (!storage.isOpen()) { 39 | return Wallet{}; 40 | } 41 | } 42 | priv *d = new priv(address); 43 | 44 | for (Pool pool = Pool::load(storage.last_hash(), storage); pool.is_valid(); pool = Pool::load(pool.previous_hash(), storage)) { 45 | for (size_t i = 0; i < pool.transactions_count(); ++i) { 46 | const Transaction t = pool.transaction(i); 47 | const Currency currency = t.currency(); 48 | if (t.source() == address) { 49 | d->amounts_[currency] -= t.amount(); 50 | } 51 | if (t.target() == address) { 52 | d->amounts_[currency] += t.amount(); 53 | } 54 | } 55 | } 56 | 57 | return Wallet(d); 58 | } 59 | 60 | } // namespace csdb 61 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_binary_streams.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CREDITSCOM/node/43ecbaca02fb83e1e5e3f7e77243de44dee86870/csdb/unittests/csdb_unit_tests_binary_streams.cpp -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_database.cpp: -------------------------------------------------------------------------------- 1 | #include "csdb/database.h" 2 | 3 | #include 4 | 5 | #include "csdb/internal/utils.h" 6 | 7 | class DatabaseTest : public ::testing::Test 8 | { 9 | protected: 10 | class DatabaseImpl : public ::csdb::Database 11 | { 12 | private: 13 | bool is_open() const override final {return false;} 14 | bool put(const byte_array&, const byte_array&) override final {return false;} 15 | bool get(const byte_array&, byte_array*) override final {return false;} 16 | bool remove(const byte_array&) override final {return false;} 17 | bool write_batch(const ItemList&) override final {return false;} 18 | IteratorPtr new_iterator() override final {return IteratorPtr{nullptr};} 19 | 20 | public: 21 | using ::csdb::Database::set_last_error; 22 | }; 23 | }; 24 | 25 | TEST_F(DatabaseTest, LastError) 26 | { 27 | DatabaseImpl db; 28 | EXPECT_EQ(db.last_error(), ::csdb::Database::NoError); 29 | EXPECT_FALSE(db.last_error_message().empty()); 30 | 31 | db.set_last_error(::csdb::Database::NotFound); 32 | EXPECT_EQ(db.last_error(), ::csdb::Database::NotFound); 33 | EXPECT_FALSE(db.last_error_message().empty()); 34 | 35 | db.set_last_error(::csdb::Database::Corruption, nullptr); 36 | EXPECT_EQ(db.last_error(), ::csdb::Database::Corruption); 37 | EXPECT_FALSE(db.last_error_message().empty()); 38 | 39 | db.set_last_error(::csdb::Database::NotSupported, std::string("Test")); 40 | EXPECT_EQ(db.last_error(), ::csdb::Database::NotSupported); 41 | EXPECT_EQ(db.last_error_message(), "Test"); 42 | 43 | db.set_last_error(::csdb::Database::InvalidArgument, "Test"); 44 | EXPECT_EQ(db.last_error(), ::csdb::Database::InvalidArgument); 45 | EXPECT_EQ(db.last_error_message(), "Test"); 46 | 47 | db.set_last_error(::csdb::Database::IOError, "%s%04u", "Test", 100); 48 | EXPECT_EQ(db.last_error(), ::csdb::Database::IOError); 49 | EXPECT_EQ(db.last_error_message(), "Test0100"); 50 | 51 | db.set_last_error(); 52 | EXPECT_EQ(db.last_error(), ::csdb::Database::NoError); 53 | EXPECT_FALSE(db.last_error_message().empty()); 54 | } 55 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_endian.cpp: -------------------------------------------------------------------------------- 1 | #include "csdb/internal/endian.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace { 8 | typedef ::testing::Types< 9 | int8_t, uint8_t, 10 | int16_t, uint16_t, 11 | int32_t, uint32_t, 12 | int64_t, uint64_t, 13 | intmax_t, uintmax_t 14 | > TypesForTest; 15 | } 16 | 17 | template 18 | class EndianTest : public ::testing::Test 19 | { 20 | protected: 21 | void SetUp() override 22 | { 23 | uint8_t buf_l[sizeof(Type)]; 24 | uint8_t buf_b[sizeof(Type)]; 25 | platform_endian_ = 0; 26 | for (uint8_t i = 0; i < sizeof(Type); ++i) { 27 | buf_l[sizeof(Type) - i - 1] = buf_b[i] = (i + 1); 28 | platform_endian_ = static_cast((platform_endian_ * 256) + (i + 1)); 29 | } 30 | memcpy(&little_endian_, buf_l, sizeof(Type)); 31 | memcpy(&big_endian_, buf_b, sizeof(Type)); 32 | } 33 | 34 | typedef T Type; 35 | Type little_endian_; 36 | Type big_endian_; 37 | Type platform_endian_; 38 | }; 39 | 40 | TYPED_TEST_CASE(EndianTest, TypesForTest); 41 | 42 | TYPED_TEST(EndianTest, ReverseByteOrder) 43 | { 44 | EXPECT_EQ(this->little_endian_, ::csdb::internal::reverse_byte_order(this->big_endian_)); 45 | EXPECT_EQ(this->big_endian_, ::csdb::internal::reverse_byte_order(this->little_endian_)); 46 | } 47 | 48 | TYPED_TEST(EndianTest, EndianConvertes) 49 | { 50 | EXPECT_EQ(this->little_endian_, ::csdb::internal::to_little_endian(this->platform_endian_)); 51 | EXPECT_EQ(this->platform_endian_, ::csdb::internal::from_little_endian(this->little_endian_)); 52 | 53 | EXPECT_EQ(this->big_endian_, ::csdb::internal::to_big_endian(this->platform_endian_)); 54 | EXPECT_EQ(this->platform_endian_, ::csdb::internal::from_big_endian(this->big_endian_)); 55 | } 56 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_environment.cpp: -------------------------------------------------------------------------------- 1 | #include "csdb_unit_tests_environment.h" 2 | 3 | namespace csdb { 4 | 5 | bool operator ==(const Transaction& a, const Transaction& b) 6 | { 7 | if (!((a.source() == b.source()) 8 | && (a.target() == b.target()) 9 | && (a.currency() == b.currency()) 10 | && (a.amount() == b.amount()) 11 | && (a.balance() == b.balance()))) { 12 | return false; 13 | } 14 | 15 | auto ids = a.user_field_ids(); 16 | if (ids != b.user_field_ids()) { 17 | return false; 18 | } 19 | 20 | for (auto id : ids) { 21 | if (a.user_field(id) != b.user_field(id)) { 22 | return false; 23 | } 24 | } 25 | 26 | return true; 27 | } 28 | 29 | bool operator ==(const Pool& a, const Pool& b) 30 | { 31 | if (a.is_valid() != b.is_valid()) { 32 | return false; 33 | } 34 | 35 | if (!a.is_valid()) { 36 | return true; 37 | } 38 | 39 | if ((a.is_read_only() != b.is_read_only()) 40 | || (a.sequence() != b.sequence()) 41 | || (a.previous_hash() != b.previous_hash()) 42 | || (a.transactions_count() != b.transactions_count()) 43 | ) { 44 | return false; 45 | } 46 | 47 | if (a.is_read_only()) { 48 | if (a.hash() != b.hash()) { 49 | return false; 50 | } 51 | } 52 | 53 | for (size_t i = 0; i < a.transactions_count(); ++i) { 54 | if (a.transaction(i) != b.transaction(i)) { 55 | return false; 56 | } 57 | } 58 | 59 | auto ids = a.user_field_ids(); 60 | if (ids != b.user_field_ids()) { 61 | return false; 62 | } 63 | 64 | for (auto id : ids) { 65 | if (a.user_field(id) != b.user_field(id)) { 66 | return false; 67 | } 68 | } 69 | 70 | return true; 71 | } 72 | 73 | } // namespace csdb 74 | 75 | ::std::ostream& operator <<(::std::ostream& os, const ::csdb::UserField& value) 76 | { 77 | os << "{"; 78 | switch (value.type()) { 79 | case ::csdb::UserField::Integer: 80 | os << "Integer: " << value.value(); 81 | break; 82 | 83 | case ::csdb::UserField::String: 84 | os << "String: \"" << value.value<::std::string>() << "\""; 85 | break; 86 | 87 | case ::csdb::UserField::Amount: 88 | os << "Amount: " << value.value<::csdb::Amount>(); 89 | break; 90 | 91 | default: 92 | os << ""; 93 | break; 94 | } 95 | os << "}"; 96 | return os; 97 | } 98 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_environment.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file csdb_unit_tests_environment.h 3 | * @author Evgeny V. Zalivochkin 4 | */ 5 | 6 | #pragma once 7 | #ifndef _CREDITS_CSDB_UNIT_TESTS_ENVIRONMENT_H_INCLUDED_ 8 | #define _CREDITS_CSDB_UNIT_TESTS_ENVIRONMENT_H_INCLUDED_ 9 | 10 | #include 11 | 12 | #include "csdb/address.h" 13 | #include "csdb/amount.h" 14 | #include "csdb/currency.h" 15 | #include "csdb/transaction.h" 16 | #include "csdb/pool.h" 17 | #include "csdb/user_field.h" 18 | 19 | #include 20 | 21 | namespace csdb { 22 | 23 | bool operator ==(const Transaction& a, const Transaction& b); 24 | 25 | inline bool operator !=(const Transaction& a, const Transaction& b) 26 | { 27 | return !(a == b); 28 | } 29 | 30 | bool operator ==(const Pool& a, const Pool& b); 31 | 32 | inline bool operator !=(const Pool& a, const Pool& b) 33 | { 34 | return !(a == b); 35 | } 36 | 37 | } // namespace csdb 38 | 39 | ::std::ostream& operator <<(::std::ostream& os, const ::csdb::UserField& value); 40 | 41 | #endif // _CREDITS_CSDB_UNIT_TESTS_ENVIRONMENT_H_INCLUDED_ 42 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_main.cpp: -------------------------------------------------------------------------------- 1 | #include "csdb/csdb.h" 2 | 3 | #include 4 | 5 | #include "leveldb/env.h" 6 | 7 | #include 8 | 9 | int main(int argc, char** argv) 10 | { 11 | #if defined(__MINGW32__) 12 | std::setlocale(LC_ALL, "Russian"); 13 | #elif defined(_WIN32) 14 | std::setlocale(LC_ALL, "ru-RU"); 15 | #else 16 | std::setlocale(LC_ALL, "ru_RU.UTF-8"); 17 | #endif 18 | 19 | ::testing::InitGoogleTest(&argc, argv); 20 | 21 | return RUN_ALL_TESTS(); 22 | } 23 | 24 | TEST(Init, Done) 25 | { 26 | std::string path_to_tests; 27 | leveldb::Env *env = leveldb::Env::Default(); 28 | EXPECT_TRUE(env->GetTestDirectory(&path_to_tests).ok()); 29 | path_to_tests += "/csdb_unittests"; 30 | if (!env->FileExists(path_to_tests)) { 31 | EXPECT_TRUE(env->CreateDir(path_to_tests).ok()); 32 | } 33 | 34 | EXPECT_FALSE(::csdb::isInitialized()); 35 | EXPECT_EQ(::csdb::lastError(), ::csdb::Storage::NoError); 36 | EXPECT_EQ(::csdb::dbLastError(), ::csdb::Database::NotOpen); 37 | EXPECT_FALSE(::csdb::lastErrorMessage().empty()); 38 | EXPECT_FALSE(::csdb::dbLastErrorMessage().empty()); 39 | 40 | EXPECT_FALSE(::csdb::init("/dev/null")); 41 | EXPECT_FALSE(::csdb::isInitialized()); 42 | EXPECT_EQ(::csdb::lastError(), ::csdb::Storage::DatabaseError); 43 | EXPECT_EQ(::csdb::dbLastError(), ::csdb::Database::IOError); 44 | 45 | EXPECT_TRUE(::csdb::init(path_to_tests.c_str())); 46 | EXPECT_TRUE(::csdb::isInitialized()); 47 | EXPECT_EQ(::csdb::lastError(), ::csdb::Storage::NoError); 48 | EXPECT_EQ(::csdb::dbLastError(), ::csdb::Database::NoError); 49 | 50 | EXPECT_FALSE(::csdb::init(path_to_tests.c_str())); 51 | EXPECT_TRUE(::csdb::isInitialized()); 52 | EXPECT_EQ(::csdb::lastError(), ::csdb::Storage::NoError); 53 | EXPECT_EQ(::csdb::dbLastError(), ::csdb::Database::NoError); 54 | 55 | csdb::done(); 56 | EXPECT_FALSE(::csdb::isInitialized()); 57 | EXPECT_EQ(::csdb::lastError(), ::csdb::Storage::NoError); 58 | EXPECT_EQ(::csdb::dbLastError(), ::csdb::Database::NotOpen); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_shared_data.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file csdb_unit_tests_shared_data.h 3 | * @author Evgeny V. Zalivochkin 4 | */ 5 | 6 | #pragma once 7 | #ifndef _CREDITS_CSDB_UNIT_TESTS_SHARED_DATA_H_INCLUDED_ 8 | #define _CREDITS_CSDB_UNIT_TESTS_SHARED_DATA_H_INCLUDED_ 9 | 10 | #include "csdb/internal/shared_data.h" 11 | #include 12 | 13 | class TestSharedData 14 | { 15 | SHARED_DATA_CLASS_DECLARE(TestSharedData) 16 | 17 | public: 18 | explicit TestSharedData(int value); 19 | bool is_copied() const; 20 | bool is_same(const TestSharedData &other) const; 21 | 22 | int value() const; 23 | void setValue(int new_value); 24 | 25 | static int counter(); 26 | }; 27 | 28 | #endif // _CREDITS_CSDB_UNIT_TESTS_SHARED_DATA_H_INCLUDED_ 29 | -------------------------------------------------------------------------------- /csdb/unittests/csdb_unit_tests_shared_data_p.cpp: -------------------------------------------------------------------------------- 1 | #include "csdb_unit_tests_shared_data.h" 2 | 3 | #include "csdb/internal/shared_data_ptr_implementation.h" 4 | 5 | class TestSharedData::priv : public csdb::internal::shared_data 6 | { 7 | public: 8 | priv() 9 | { 10 | ++counter_; 11 | } 12 | 13 | priv(int value) : value_(value) 14 | { 15 | ++counter_; 16 | } 17 | 18 | priv(const priv& other) : 19 | csdb::internal::shared_data(other), 20 | copy_constuctor_called_(true) 21 | { 22 | ++counter_; 23 | } 24 | 25 | ~priv() 26 | { 27 | --counter_; 28 | } 29 | 30 | public: 31 | bool copy_constuctor_called_ = false; 32 | int value_ = 0; 33 | static std::atomic counter_; 34 | 35 | friend class SharedDataTest; 36 | }; 37 | 38 | std::atomic TestSharedData::priv::counter_(0); 39 | 40 | SHARED_DATA_CLASS_IMPLEMENTATION(TestSharedData) 41 | 42 | TestSharedData::TestSharedData(int value) : d(new TestSharedData::priv(value)) 43 | { 44 | } 45 | 46 | bool TestSharedData::is_copied() const 47 | { 48 | return d->copy_constuctor_called_; 49 | } 50 | 51 | bool TestSharedData::is_same(const TestSharedData &other) const 52 | { 53 | return (&(*d)) == (&(*other.d)); 54 | } 55 | 56 | int TestSharedData::value() const 57 | { 58 | return d->value_; 59 | } 60 | 61 | void TestSharedData::setValue(int new_value) 62 | { 63 | d->value_ = new_value; 64 | } 65 | 66 | int TestSharedData::counter() 67 | { 68 | return TestSharedData::priv::counter_; 69 | } 70 | -------------------------------------------------------------------------------- /csnode/include/csnode/address_serializer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ADDRESS_SERIALIZER_HPP 2 | #define ADDRESS_SERIALIZER_HPP 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace boost { 10 | namespace serialization { 11 | template 12 | void save(Archive& ar, const csdb::Address& address, [[maybe_unused]] unsigned int version) { 13 | bool isId = address.is_wallet_id(); 14 | ar & isId; 15 | if (isId) { 16 | ar & address.wallet_id(); 17 | } else { 18 | ar & address.public_key(); 19 | } 20 | } 21 | template 22 | void load(Archive& ar, csdb::Address& address, [[maybe_unused]] unsigned int version) { 23 | bool isId; 24 | ar & isId; 25 | if (isId) { 26 | csdb::Address::WalletId wId; 27 | ar & wId; 28 | address = csdb::Address::from_wallet_id(wId); 29 | } else { 30 | cs::PublicKey pKey; 31 | ar & pKey; 32 | address = csdb::Address::from_public_key(pKey); 33 | } 34 | } 35 | } // namespace serialization 36 | } // namespace boost 37 | BOOST_SERIALIZATION_SPLIT_FREE(csdb::Address) 38 | #endif // ADDRESS_SERIALIZER_HPP 39 | -------------------------------------------------------------------------------- /csnode/include/csnode/blockchain_serializer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BLOCKCHAIN_SERIALIZER_HPP 2 | #define BLOCKCHAIN_SERIALIZER_HPP 3 | #include 4 | #include 5 | #include 6 | 7 | #include "csdb/amount.hpp" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | class BlockChain; 18 | 19 | namespace cs { 20 | class BlockChain_Serializer { 21 | public: 22 | void bind(BlockChain&, std::set& initialConfidants); 23 | void save(const std::filesystem::path& rootDir); 24 | void load(const std::filesystem::path& rootDir); 25 | void clear(const std::filesystem::path& rootDir); 26 | 27 | ::cscrypto::Hash hash(); 28 | 29 | private: 30 | 31 | struct NonEmptyBlockData { 32 | friend class boost::serialization::access; 33 | template 34 | void serialize(Archive &ar, [[maybe_unused]] const unsigned int version) { 35 | ar & poolSeq; 36 | ar & transCount; 37 | } 38 | cs::Sequence poolSeq; 39 | uint32_t transCount; 40 | }; 41 | 42 | std::map *previousNonEmpty_; 43 | NonEmptyBlockData *lastNonEmptyBlock_; 44 | 45 | uint64_t *totalTransactionsCount_; 46 | std::atomic *uuid_; 47 | std::atomic *lastSequence_; 48 | std::set *initialConfidants_; 49 | 50 | int32_t *blockRewardIntegral_; 51 | uint64_t* blockRewardFraction_; 52 | int32_t* miningCoefficientIntegral_; 53 | uint64_t* miningCoefficientFraction_; 54 | bool *stakingOn_; 55 | bool *miningOn_; 56 | uint32_t *TimeMinStage1_; 57 | }; 58 | } // namespace cs 59 | #endif // BLOCKCHAIN_SERIALIZER_HPP 60 | -------------------------------------------------------------------------------- /csnode/include/csnode/blockhashes.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BLOCKHASHES_HPP 2 | #define BLOCKHASHES_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace cs { 10 | class BlockHashes { 11 | public: 12 | explicit BlockHashes(const std::string& path); 13 | ~BlockHashes() = default; 14 | 15 | bool empty() const { 16 | return size() == 0; 17 | } 18 | 19 | size_t size() const; 20 | 21 | void close(); 22 | bool onNextBlock(const csdb::Pool& block) { 23 | return update(block); 24 | } 25 | 26 | csdb::PoolHash find(cs::Sequence seq) const; 27 | cs::Sequence find(const csdb::PoolHash& hash) const; 28 | 29 | bool update(const csdb::Pool& block); 30 | 31 | bool remove(cs::Sequence); 32 | bool remove(const csdb::PoolHash& hash); 33 | 34 | private slots: 35 | void onDbFailed(const cs::LmdbException& exception); 36 | 37 | private: 38 | void initialization(); 39 | 40 | cs::Lmdb seqDb_; 41 | cs::Lmdb hashDb_; 42 | }; 43 | } // namespace cs 44 | 45 | #endif // BLOCKHASHES_HPP 46 | -------------------------------------------------------------------------------- /csnode/include/csnode/blockvalidator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BLOCK_VALIDATOR_HPP 2 | #define BLOCK_VALIDATOR_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | class Node; 10 | class BlockChain; 11 | 12 | namespace cs { 13 | 14 | class ValidationPlugin; 15 | class WalletsState; 16 | 17 | class BlockValidator { 18 | public: 19 | using ValidationFlags = uint32_t; 20 | 21 | enum ValidationLevel : uint32_t { 22 | noValidation = 0, 23 | hashIntergrity = 1, 24 | blockNum = 1 << 1, 25 | timestamp = 1 << 2, 26 | blockSignatures = 1 << 3, 27 | smartSignatures = 1 << 4, 28 | balances = 1 << 5, 29 | transactionsSignatures = 1 << 6, 30 | smartStates = 1 << 7, 31 | accountBalance = 1 << 8, 32 | balancesOnly = 1 << 9 33 | }; 34 | 35 | enum SeverityLevel : uint8_t { 36 | warningsAsErrors = 1, 37 | greaterThanWarnings, 38 | onlyFatalErrors 39 | }; 40 | 41 | explicit BlockValidator(Node&); 42 | ~BlockValidator(); 43 | bool validateBlock(const csdb::Pool&, ValidationFlags = hashIntergrity, SeverityLevel = greaterThanWarnings); 44 | 45 | BlockValidator(const BlockValidator&) = delete; 46 | BlockValidator(BlockValidator&&) = delete; 47 | BlockValidator& operator=(const BlockValidator&) = delete; 48 | BlockValidator& operator=(BlockValidator&&) = delete; 49 | 50 | private: 51 | enum ErrorType : uint8_t { 52 | noError = 0, 53 | warning = 1 << 1, 54 | error = 1 << 2, 55 | fatalError = 1 << 3 56 | }; 57 | 58 | bool return_(ErrorType, SeverityLevel); 59 | 60 | Node& node_; 61 | const BlockChain& bc_; 62 | 63 | std::map> plugins_; 64 | 65 | friend class ValidationPlugin; 66 | 67 | std::shared_ptr wallets_; 68 | csdb::Pool prevBlock_; 69 | }; 70 | } // namespace cs 71 | #endif // BLOCKVALIDATOR_HPP 72 | -------------------------------------------------------------------------------- /csnode/include/csnode/caches_serialization_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | class BlockChain; 10 | class TokensMaster; 11 | 12 | namespace api { 13 | 14 | class APIHandler; 15 | 16 | } // namespace api 17 | 18 | namespace cs { 19 | 20 | class SmartContracts; 21 | class WalletsCache; 22 | class WalletsIds; 23 | class RoundStat; 24 | 25 | class CachesSerializationManager { 26 | public: 27 | CachesSerializationManager(); 28 | ~CachesSerializationManager(); 29 | 30 | void bind(BlockChain&, std::set& initialConfidants); 31 | void bind(SmartContracts&); 32 | void bind(WalletsCache&); 33 | void bind(WalletsIds&); 34 | void bind(RoundStat&); 35 | void bind(TokensMaster&); 36 | void bind(api::APIHandler&); 37 | 38 | void clear(size_t version = 0); 39 | 40 | bool save(size_t version = 0); 41 | bool load(); 42 | 43 | private: 44 | struct Impl; 45 | std::unique_ptr pImpl_; 46 | }; 47 | 48 | } // namespace cs 49 | -------------------------------------------------------------------------------- /csnode/include/csnode/configholder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGHOLDER_HPP 2 | #define CONFIGHOLDER_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | class Config; 10 | 11 | namespace cs { 12 | class ConfigHolder { 13 | ConfigHolder(); 14 | ~ConfigHolder(); 15 | 16 | public: 17 | static ConfigHolder& instance(); 18 | 19 | void setConfig(const Config& config); 20 | const Config* config() const; 21 | 22 | public slots: 23 | void onConfigChanged(const Config& config); 24 | 25 | private: 26 | cs::LockFreeChanger config_; 27 | }; 28 | } // namespace cs 29 | #endif // CONFIGHOLDER_HPP 30 | -------------------------------------------------------------------------------- /csnode/include/csnode/confirmationlist.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONFIRMATIONLIST_HPP 2 | #define CONFIRMATIONLIST_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace cs { 12 | struct TrustedConfirmation { 13 | bool bigBang = false; 14 | cs::ConfidantsKeys confidants; 15 | cs::Bytes mask; 16 | cs::Signatures signatures; 17 | }; 18 | 19 | class ConfirmationList { 20 | public: 21 | void add(cs::RoundNumber rNum, bool bang, const cs::ConfidantsKeys& confidants, const cs::Bytes& confirmationsMask, const cs::Signatures& confirmation); 22 | void remove(cs::RoundNumber); 23 | std::optional find(cs::RoundNumber) const; 24 | 25 | private: 26 | // confidant confirmation 27 | std::map confirmationList_; 28 | }; 29 | } // namespace cs 30 | 31 | #endif // CONFIRMATIONLIST_HPP 32 | -------------------------------------------------------------------------------- /csnode/include/csnode/cyclicbuffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CYCLIC_BUFFER_H 2 | #define CYCLIC_BUFFER_H 3 | 4 | #include 5 | 6 | template 7 | class CyclicBuffer { 8 | public: 9 | CyclicBuffer() 10 | : size_(0) 11 | , back_(0) { 12 | } 13 | 14 | void push_back(const T& val) { 15 | back_ = (back_ + 1) % N; 16 | data_[back_] = val; 17 | ++size_; 18 | } 19 | 20 | T& back() { 21 | return data_[back_]; 22 | } 23 | const T& back() const { 24 | return data_[back_]; 25 | } 26 | 27 | void pop_back() { 28 | back_ = (back_ - 1 + N) % N; 29 | --size_; 30 | } 31 | 32 | void push_front(const T& val) { 33 | size_t ind = (back_ - size_ + N) % N; 34 | data_[ind] = val; 35 | ++size_; 36 | } 37 | 38 | T& front() { 39 | return data_[getFrontInd(0)]; 40 | } 41 | const T& front() const { 42 | return data_[getFrontInd(0)]; 43 | } 44 | 45 | void pop_front() { 46 | --size_; 47 | } 48 | 49 | T& operator[](size_t ind) { 50 | return data_[getFrontInd(ind)]; 51 | } 52 | const T& operator[](size_t ind) const { 53 | return data_[getFrontInd(ind)]; 54 | } 55 | 56 | bool full() const { 57 | return size_ == N; 58 | } 59 | bool empty() const { 60 | return !size_; 61 | } 62 | size_t size() const { 63 | return size_; 64 | } 65 | 66 | private: 67 | size_t getFrontInd(size_t offset) const { 68 | decltype(N) frontInd = back_ + 1 - size_; 69 | return (frontInd + static_cast(offset) + N) % N; 70 | } 71 | 72 | private: 73 | T data_[N]; 74 | decltype(N) size_; 75 | decltype(N) back_; 76 | }; 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /csnode/include/csnode/datastream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DATASTREAM_HPP 2 | #define DATASTREAM_HPP 3 | 4 | #include 5 | #include 6 | 7 | #endif // DATASTREAM_HPP 8 | -------------------------------------------------------------------------------- /csnode/include/csnode/fee.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SOLVER_FEE_HPP 2 | #define SOLVER_FEE_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace cs { 12 | 13 | class SmartContracts; 14 | 15 | namespace fee { 16 | 17 | using Transactions = std::vector; 18 | 19 | /// 20 | /// @brief sets counted fee for each transaction in passed container 21 | /// 22 | void setCountedFees(Transactions&); 23 | 24 | /// 25 | /// @brief allows to obtain fee for the given transactions size 26 | /// @return fee depending of the transaction size 27 | /// 28 | csdb::AmountCommission justFee(const size_t size); 29 | /// 30 | /// @brief allows to estimate weather max fee is enough before consensus 31 | /// @return true if max fee >= countedFee 32 | /// 33 | bool estimateMaxFee(const csdb::Transaction&, csdb::AmountCommission& countedFee, SmartContracts& sc); 34 | 35 | /// 36 | /// @return counted fee for transaction 37 | /// 38 | csdb::AmountCommission getFee(const csdb::Transaction&); 39 | 40 | /// 41 | /// @return minimal fee for contract new state transaction 42 | /// 43 | csdb::AmountCommission getContractStateMinFee(); 44 | 45 | /// Gets execution fee. 46 | /// 47 | /// Alexander Avramenko, 11.06.2019. 48 | /// 49 | /// The measured duration in microseconds. 50 | /// 51 | /// The execution fee. 52 | 53 | csdb::Amount getExecutionFee(long long duration_mcs); 54 | 55 | } // namespace fee 56 | } // namespace cs 57 | #endif // SOLVER_FEE_HPP 58 | -------------------------------------------------------------------------------- /csnode/include/csnode/nodeutils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef NODEUTILS_HPP 2 | #define NODEUTILS_HPP 3 | 4 | #include 5 | 6 | namespace csdb { 7 | class Pool; 8 | } 9 | 10 | namespace cs { 11 | class NodeUtils { 12 | public: 13 | static bool checkGroupSignature(const cs::ConfidantsKeys& confidants, const cs::Bytes& mask, const cs::Signatures& signatures, const cs::Hash& hash); 14 | static size_t realTrustedValue(const cs::Bytes& mask); 15 | static cs::Bytes getTrustedMask(const csdb::Pool& block); 16 | static std::string roundsToString(const std::vector& rounds); 17 | }; 18 | } // namespace cs 19 | 20 | #endif // NODEUTILS_HPP 21 | -------------------------------------------------------------------------------- /csnode/include/csnode/packetqueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PACKETQUEUE_HPP 2 | #define PACKETQUEUE_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace cs { 11 | // implements business logic for transpaction packet 12 | class PacketQueue : public boost::noncopyable { 13 | public: 14 | explicit PacketQueue(size_t queueSize, size_t transactionsSize, size_t packetsPerRound); 15 | ~PacketQueue() = default; 16 | 17 | bool push(const csdb::Transaction& transaction); 18 | void push(const cs::TransactionsPacket& packet); 19 | 20 | cs::PacketsVector pop(); 21 | 22 | std::deque::const_iterator begin() const; 23 | std::deque::const_iterator end() const; 24 | 25 | size_t size() const; 26 | bool isEmpty() const; 27 | std::deque::const_reference back() const; 28 | 29 | private: 30 | std::deque queue_; 31 | 32 | size_t maxQueueSize_; 33 | size_t maxTransactionsSize_; 34 | size_t maxPacketsPerRound_; 35 | 36 | cs::RoundNumber cachedRound_; 37 | size_t cachedPackets_; 38 | }; 39 | } 40 | 41 | #endif // PACKETQUEUE_HPP 42 | -------------------------------------------------------------------------------- /csnode/include/csnode/roundpackage.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ROUNDPACKAGE_HPP 2 | #define ROUNDPACKAGE_HPP 3 | 4 | #include 5 | 6 | namespace cs { 7 | class RoundPackage { 8 | public: 9 | RoundPackage(); 10 | 11 | const cs::Bytes& toBinary(bool showVersion); 12 | cs::Byte subRound(); 13 | bool fromBinary(const cs::Bytes& bytes, cs::RoundNumber rNum, cs::Byte subRound); 14 | 15 | std::string toString(); 16 | cs::Bytes bytesToSign(bool showVersion); 17 | const cs::RoundTable& roundTable() const; 18 | const cs::PoolMetaInfo& poolMetaInfo() const; 19 | 20 | void updateRoundTable(const cs::RoundTable& roundTable); 21 | void updatePoolMeta(const cs::PoolMetaInfo& meta); 22 | void updateRoundSignatures(const cs::Signatures& signatures); 23 | void updatePoolSignatures(const cs::Signatures& signatures); 24 | void updateTrustedSignatures(const cs::Signatures& signatures); 25 | 26 | const cs::Signatures& roundSignatures() const; 27 | const cs::Signatures& poolSignatures() const; 28 | const cs::Signatures& trustedSignatures() const; 29 | size_t messageLength(); 30 | 31 | cs::Byte iteration() { 32 | return iteration_; 33 | } 34 | 35 | cs::Byte subround() { 36 | return subRound_; 37 | } 38 | 39 | // store sender key with round package 40 | void setSenderNode(const cs::PublicKey& sender); 41 | 42 | bool hasSender() const { 43 | return bool(sender_); 44 | } 45 | 46 | bool getSender(cs::PublicKey& sender) const; 47 | 48 | private: 49 | std::string name() { 50 | return "RoundPackage> "; 51 | } 52 | 53 | void refillToSign(bool showVersion); 54 | 55 | cs::RoundTable roundTable_; 56 | cs::PoolMetaInfo poolMetaInfo_; // confirmations sent in rt are confirmations for next pool 57 | 58 | cs::Signatures roundSignatures_; 59 | cs::Signatures poolSignatures_; 60 | cs::Signatures trustedSignatures_; 61 | 62 | std::vector smartSignatures_; 63 | 64 | cs::Bytes binaryRepresentation_; 65 | size_t messageSize_ = 0; 66 | cs::Byte iteration_ = 0U; 67 | cs::Byte subRound_ = 0U; 68 | 69 | std::shared_ptr sender_; 70 | }; 71 | } // namespace cs 72 | 73 | #endif // ROUNDPACKAGE_HPP 74 | -------------------------------------------------------------------------------- /csnode/include/csnode/roundstat_serializer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ROUNDSTAT_SERIALIZER_HPP 2 | #define ROUNDSTAT_SERIALIZER_HPP 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | 15 | namespace cs { 16 | class RoundStat; 17 | class RoundStat_Serializer { 18 | public: 19 | void bind(RoundStat& roundStat); 20 | void save(const std::filesystem::path& rootDir); 21 | void load(const std::filesystem::path& rootDir); 22 | void clear(const std::filesystem::path& rootDir); 23 | void printClassInfo(); 24 | ::cscrypto::Hash hash(); 25 | 26 | private: 27 | RoundStat* roundStat_; 28 | }; 29 | } 30 | 31 | #endif -------------------------------------------------------------------------------- /csnode/include/csnode/sendcachedata.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SENDCACHEDATA_HPP 2 | #define SENDCACHEDATA_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace cs { 9 | class SendCacheData { 10 | public: 11 | SendCacheData(); 12 | explicit SendCacheData(const cs::TransactionsPacketHash& hash); 13 | explicit SendCacheData(const cs::TransactionsPacketHash& hash, size_t count); 14 | 15 | const cs::TransactionsPacketHash& hash() const { 16 | return hash_; 17 | } 18 | 19 | size_t count() const { 20 | return count_; 21 | } 22 | 23 | private: 24 | cs::TransactionsPacketHash hash_; 25 | size_t count_; 26 | }; 27 | 28 | // send transactions packet cache for conveyer 29 | using TransactionPacketSendCache = std::multimap; 30 | } // namespace cs 31 | 32 | #endif // SENDCACHEDATA_HPP 33 | -------------------------------------------------------------------------------- /csnode/include/csnode/serializers_helper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace cs { 8 | 9 | class SerializersHelper { 10 | public: 11 | static ::cscrypto::Hash getHashFromFile(const std::string& fileName) { 12 | static const size_t kBufSize = 1 << 27; 13 | std::vector buf(::cscrypto::kHashSize + kBufSize, 0); 14 | { 15 | std::ifstream ifs(fileName); 16 | while (!ifs.eof()) { 17 | ifs.read( 18 | reinterpret_cast(buf.data() + ::cscrypto::kHashSize), 19 | kBufSize 20 | ); 21 | auto hash = ::cscrypto::calculateHash(buf.data(), buf.size()); 22 | std::copy(hash.begin(), hash.end(), buf.begin()); 23 | } 24 | } 25 | 26 | ::cscrypto::Hash result; 27 | std::copy( 28 | buf.begin(), 29 | std::next(buf.begin(), ::cscrypto::kHashSize), 30 | result.begin() 31 | ); 32 | return result; 33 | } 34 | }; 35 | 36 | } // namespace cs 37 | -------------------------------------------------------------------------------- /csnode/include/csnode/smartcontracts_serializer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SMARTCONTRACTS_SERIALIZER_HPP 2 | #define SMARTCONTRACTS_SERIALIZER_HPP 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "address_serializer.hpp" 19 | 20 | class SmartContracts; 21 | class SmartConsensus; 22 | //class csdb::Transaction; 23 | 24 | namespace cs { 25 | 26 | 27 | class SmartContracts_Serializer { 28 | public: 29 | void bind(SmartContracts&); 30 | void save(const std::filesystem::path& rootDir); 31 | void load(const std::filesystem::path& rootDir); 32 | void clear(const std::filesystem::path& rootDir); 33 | ::cscrypto::Hash hash(); 34 | 35 | 36 | 37 | private: 38 | SmartContracts* contracts_; 39 | }; 40 | } // namespace cs 41 | #endif // SMARTCONTRACTS_SERIALIZER_HPP 42 | -------------------------------------------------------------------------------- /csnode/include/csnode/transactionsindex.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TRANSACTIONSINDEX_HPP 2 | #define TRANSACTIONSINDEX_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class BlockChain; 14 | 15 | namespace csdb { 16 | class Pool; 17 | } // namespace csdb 18 | 19 | namespace cs { 20 | 21 | class TransactionsIndex { 22 | public: 23 | TransactionsIndex(BlockChain&, const std::string& _path, bool _recreate = false); 24 | ~TransactionsIndex() = default; 25 | 26 | void update(const csdb::Pool&); 27 | void invalidate(); 28 | void close(); 29 | 30 | bool recreate() const; 31 | 32 | Sequence getPrevTransBlock(const csdb::Address& _addr, Sequence _curr) const; 33 | 34 | public slots: 35 | void onStartReadFromDb(Sequence _lastWrittenPoolSeq); 36 | void onReadFromDb(const csdb::Pool&); 37 | void onDbReadFinished(); 38 | void onRemoveBlock(const csdb::Pool&); 39 | 40 | private slots: 41 | void onDbFailed(const LmdbException&); 42 | 43 | private: 44 | void init(); 45 | void reset(); 46 | 47 | void updateFromNextBlock(const csdb::Pool&); 48 | void updateLastIndexed(); 49 | 50 | static bool hasToRecreate(const std::string&, cs::Sequence&); 51 | 52 | void setPrevTransBlock(const PublicKey&, cs::Sequence _curr, cs::Sequence _prev); 53 | void removeLastTransBlock(const PublicKey&, cs::Sequence _curr); 54 | 55 | BlockChain& bc_; 56 | const std::string rootPath_; 57 | std::unique_ptr db_; 58 | Sequence lastIndexedPool_ = 0; 59 | bool recreate_; 60 | MMappedFileWrap lastIndexedFile_; 61 | 62 | std::map lapoos_; 63 | }; 64 | } // namespace cs 65 | #endif // TRANSACTIONSINDEX_HPP 66 | -------------------------------------------------------------------------------- /csnode/include/csnode/transactionsiterator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CSNODE_TRANSACTIONS_ITERATOR_HPP 2 | #define CSNODE_TRANSACTIONS_ITERATOR_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class BlockChain; 9 | 10 | namespace cs { 11 | 12 | class TransactionsIterator { 13 | public: 14 | TransactionsIterator(const BlockChain&, const csdb::Address&); 15 | TransactionsIterator(const BlockChain&, const csdb::Address&, const csdb::Pool&); 16 | 17 | void next(); 18 | bool isValid() const; 19 | 20 | const csdb::Pool& getPool() const { 21 | return lapoo_; 22 | } 23 | 24 | const csdb::Transaction& operator*() const { 25 | return *it_; 26 | } 27 | auto operator-> () const { 28 | return it_; 29 | } 30 | 31 | private: 32 | void setFromTransId(const csdb::TransactionID&); 33 | 34 | const BlockChain& bc_; 35 | 36 | csdb::Address addr_; 37 | csdb::Pool lapoo_; 38 | std::vector::const_reverse_iterator it_; 39 | }; 40 | 41 | } // namespace cs 42 | #endif // CSNODE_TRANSACTIONS_ITERATOR_HPP 43 | -------------------------------------------------------------------------------- /csnode/include/csnode/walletsstate.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WALLETS_STATE_HPP 2 | #define WALLETS_STATE_HPP 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace cs { 13 | class WalletsCache; 14 | class WalletsIds; 15 | 16 | class WalletsState { 17 | public: 18 | using WalletAddress = csdb::Address; 19 | using TransactionIndex = uint32_t; 20 | 21 | static constexpr TransactionIndex noInd_ = std::numeric_limits::max(); 22 | 23 | struct WalletData { 24 | TransactionIndex lastTrxInd_{}; 25 | csdb::Amount balance_{}; 26 | csdb::Amount delegated_{}; 27 | std::map> delegateSources_{}; 28 | std::map> delegateTargets_{}; 29 | TransactionsTail trxTail_{}; 30 | }; 31 | 32 | explicit WalletsState(const WalletsCache::Updater& cacheUpd) : wallCache_(cacheUpd) {} 33 | WalletData& getData(const WalletAddress& address); 34 | 35 | void updateFromSource() { storage_.clear(); } 36 | 37 | private: 38 | const WalletsCache::Updater& wallCache_; 39 | std::unordered_map storage_; 40 | }; 41 | } // namespace cs 42 | #endif // WALLETS_STATE_HPP 43 | -------------------------------------------------------------------------------- /csnode/src/configholder.cpp: -------------------------------------------------------------------------------- 1 | #include "csnode/configholder.hpp" 2 | 3 | cs::ConfigHolder& cs::ConfigHolder::instance() { 4 | static ConfigHolder holder; 5 | return holder; 6 | } 7 | 8 | void cs::ConfigHolder::onConfigChanged(const Config& config) { 9 | setConfig(config); 10 | } 11 | 12 | void cs::ConfigHolder::setConfig(const Config& config) { 13 | config_.exchange(config); 14 | } 15 | 16 | const Config* cs::ConfigHolder::config() const { 17 | return config_.operator->(); 18 | } 19 | 20 | cs::ConfigHolder::ConfigHolder() = default; 21 | cs::ConfigHolder::~ConfigHolder() = default; 22 | -------------------------------------------------------------------------------- /csnode/src/confirmationlist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace cs { 6 | void ConfirmationList::add(cs::RoundNumber rNum, bool bang, const cs::ConfidantsKeys& confidants, const cs::Bytes& confirmationsMask, const cs::Signatures& confirmation) { 7 | if (confirmationList_.find(rNum) != confirmationList_.cend()) { 8 | remove(rNum); 9 | } 10 | 11 | TrustedConfirmation tConfirmation; 12 | tConfirmation.bigBang = bang; 13 | tConfirmation.confidants = confidants; 14 | tConfirmation.mask = confirmationsMask; 15 | tConfirmation.signatures = confirmation; 16 | 17 | confirmationList_.emplace(rNum, std::move(tConfirmation)); 18 | csdebug() << "The confirmation of R-" << rNum << " added, conf.size = " << confirmationList_.size(); 19 | if (rNum > cs::values::kDefaultMetaStorageMaxSize) { 20 | for(auto it = confirmationList_.cbegin(); it != confirmationList_.cend(); /*++it*/){ 21 | auto tmp = it++; 22 | if (tmp->first < rNum - cs::values::kDefaultMetaStorageMaxSize) { 23 | confirmationList_.erase(tmp); 24 | } 25 | } 26 | csdebug() << "Some confirmations were deleted, conf.size = " << confirmationList_.size(); 27 | } 28 | 29 | } 30 | 31 | void ConfirmationList::remove(cs::RoundNumber rNum) { 32 | if (confirmationList_.find(rNum) != confirmationList_.end()) { 33 | confirmationList_.erase(rNum); 34 | csdebug() << "The confirmation of R-" << rNum << " was successfully erased, conf.size = " << confirmationList_.size(); 35 | } 36 | else { 37 | csdebug() << "Unable erase the confirmation of R-" << rNum << " was not found"; 38 | } 39 | } 40 | 41 | std::optional ConfirmationList::find(cs::RoundNumber rNum) const { 42 | const auto it = confirmationList_.find(rNum); 43 | 44 | if (it == confirmationList_.end()) { 45 | csdebug() << "The confirmation of R-" << rNum << " was not found, conf.size = " << confirmationList_.size(); 46 | return std::nullopt; 47 | } 48 | csdebug() << "The confirmation of R - " << rNum << " was found, conf.size = " << confirmationList_.size(); 49 | return std::make_optional(it->second); 50 | } 51 | } // namespace cs 52 | -------------------------------------------------------------------------------- /csnode/src/packetqueue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | cs::PacketQueue::PacketQueue(size_t queueSize, size_t transactionsSize, size_t packetsPerRound) 5 | : maxQueueSize_(queueSize) 6 | , maxTransactionsSize_(transactionsSize) 7 | , maxPacketsPerRound_(packetsPerRound) { 8 | cachedRound_ = 0; 9 | cachedPackets_ = 0; 10 | } 11 | 12 | bool cs::PacketQueue::push(const csdb::Transaction& transaction) { 13 | if (queue_.size() >= maxQueueSize_) { 14 | return false; 15 | } 16 | 17 | if (queue_.empty() || queue_.back().transactions().size() >= maxTransactionsSize_) { 18 | queue_.push_back(cs::TransactionsPacket{}); 19 | } 20 | 21 | return queue_.back().addTransaction(transaction); 22 | } 23 | 24 | void cs::PacketQueue::push(const cs::TransactionsPacket& packet) { 25 | // ignore size of queue for packs 26 | queue_.push_back(packet); 27 | queue_.push_back(cs::TransactionsPacket{}); 28 | } 29 | 30 | cs::PacketsVector cs::PacketQueue::pop() { 31 | const auto round = cs::Conveyer::instance().currentRoundNumber(); 32 | cs::PacketsVector block; 33 | 34 | if (round == cachedRound_ && cachedPackets_ >= maxPacketsPerRound_) { 35 | return block; 36 | } 37 | 38 | if (round != cachedRound_) { 39 | cachedPackets_ = 0; 40 | } 41 | 42 | while (!queue_.empty() && cachedPackets_ < maxPacketsPerRound_) { 43 | block.push_back(std::move(queue_.front())); 44 | queue_.pop_front(); 45 | 46 | ++cachedPackets_; 47 | } 48 | 49 | cachedRound_ = round; 50 | return block; 51 | } 52 | 53 | typename std::deque::const_iterator cs::PacketQueue::begin() const { 54 | return queue_.begin(); 55 | } 56 | 57 | typename std::deque::const_iterator cs::PacketQueue::end() const { 58 | return queue_.end(); 59 | } 60 | 61 | size_t cs::PacketQueue::size() const { 62 | return queue_.size(); 63 | } 64 | 65 | bool cs::PacketQueue::isEmpty() const { 66 | return queue_.empty(); 67 | } 68 | 69 | std::deque::const_reference cs::PacketQueue::back() const { 70 | return queue_.back(); 71 | } 72 | -------------------------------------------------------------------------------- /csnode/src/roundstat_serializer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include "logger.hpp" 12 | 13 | namespace { 14 | const std::string kDataFileName = "roundstat.dat"; 15 | const std::string kLogPrefix = "RoundStat_Serializer: "; 16 | } // namespace 17 | 18 | namespace cs { 19 | void RoundStat_Serializer::bind(RoundStat& roundStat) { 20 | roundStat_ = &roundStat; 21 | csdebug() << "Roundstat bindings made"; 22 | } 23 | 24 | void RoundStat_Serializer::clear(const std::filesystem::path& rootDir) { 25 | roundStat_->clear(); 26 | save(rootDir); 27 | } 28 | 29 | 30 | void RoundStat_Serializer::printClassInfo() { 31 | roundStat_->printClassInfo(); 32 | 33 | 34 | } 35 | 36 | void RoundStat_Serializer::save(const std::filesystem::path& rootDir) { 37 | std::ofstream ofs(rootDir / kDataFileName, std::ios::binary); 38 | boost::archive::binary_oarchive oa(ofs); 39 | csdebug() << kLogPrefix << __func__; 40 | roundStat_->printClassInfo(); 41 | oa << roundStat_->serialize(); 42 | } 43 | 44 | ::cscrypto::Hash RoundStat_Serializer::hash() { 45 | { 46 | std::ofstream ofs(kDataFileName, std::ios::binary); 47 | { 48 | boost::archive::binary_oarchive oa( 49 | ofs, 50 | boost::archive::no_header | boost::archive::no_codecvt 51 | ); 52 | oa << roundStat_->serialize(); 53 | //printClassInfo(); 54 | } 55 | } 56 | 57 | auto result = SerializersHelper::getHashFromFile(kDataFileName); 58 | //std::filesystem::remove(kDataFileName); 59 | return result; 60 | } 61 | 62 | 63 | void RoundStat_Serializer::load(const std::filesystem::path& rootDir) { 64 | std::ifstream ifs(rootDir / kDataFileName, std::ios::binary); 65 | boost::archive::binary_iarchive ia(ifs); 66 | csdebug() << kLogPrefix << __func__; 67 | Bytes data; 68 | ia >> data; 69 | roundStat_->deserialize(data); 70 | printClassInfo(); 71 | } 72 | } -------------------------------------------------------------------------------- /csnode/src/sendcachedata.cpp: -------------------------------------------------------------------------------- 1 | #include "sendcachedata.hpp" 2 | 3 | namespace cs { 4 | SendCacheData::SendCacheData() 5 | : count_(0) { 6 | } 7 | 8 | SendCacheData::SendCacheData(const TransactionsPacketHash& hash) 9 | : hash_(hash) 10 | , count_(0) { 11 | } 12 | 13 | SendCacheData::SendCacheData(const TransactionsPacketHash& hash, size_t count) 14 | : hash_(hash) 15 | , count_(count) { 16 | } 17 | } // namespace cs 18 | -------------------------------------------------------------------------------- /csnode/src/smartcontracts_serializer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //#include 6 | //#include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "logger.hpp" 16 | 17 | namespace { 18 | const std::string kDataFileName = "smartcontracts.dat"; 19 | const std::string kLogPrefix = "SmartContracts_Serializer: "; 20 | } // namespace 21 | 22 | namespace cs { 23 | void SmartContracts_Serializer::bind(SmartContracts& contracts) { 24 | contracts_ = &contracts; 25 | csdebug() << "Contracts bindings made"; 26 | } 27 | 28 | void SmartContracts_Serializer::clear(const std::filesystem::path& rootDir) { 29 | contracts_->clear(); 30 | save(rootDir); 31 | } 32 | 33 | void SmartContracts_Serializer::save(const std::filesystem::path& rootDir) { 34 | std::ofstream ofs(rootDir / kDataFileName, std::ios::binary); 35 | boost::archive::binary_oarchive oa(ofs); 36 | csdebug() << kLogPrefix << __func__; 37 | contracts_->printClassInfo(); 38 | oa << contracts_->serialize(); 39 | } 40 | 41 | ::cscrypto::Hash SmartContracts_Serializer::hash() { 42 | { 43 | std::ofstream ofs(kDataFileName, std::ios::binary); 44 | { 45 | boost::archive::binary_oarchive oa( 46 | ofs, 47 | boost::archive::no_header | boost::archive::no_codecvt 48 | ); 49 | csdebug() << kLogPrefix << __func__; 50 | contracts_->printClassInfo(); 51 | oa << contracts_->serialize(); 52 | } 53 | 54 | } 55 | 56 | auto result = SerializersHelper::getHashFromFile(kDataFileName); 57 | //std::filesystem::remove(kDataFileName); 58 | return result; 59 | } 60 | 61 | void SmartContracts_Serializer::load(const std::filesystem::path& rootDir) { 62 | std::ifstream ifs(rootDir / kDataFileName, std::ios::binary); 63 | boost::archive::binary_iarchive ia(ifs); 64 | csdebug() << kLogPrefix << __func__; 65 | Bytes data; 66 | ia >> data; 67 | contracts_->deserialize(data); 68 | contracts_->printClassInfo(); 69 | 70 | } 71 | } // namespace cs 72 | -------------------------------------------------------------------------------- /csnode/src/tokens_serializer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #include "logger.hpp" 13 | 14 | namespace { 15 | const std::string kDataFileName = "tokens.dat"; 16 | const std::string kLogPrefix = "TokensMaster_Serializer: "; 17 | } // namespace 18 | 19 | namespace cs { 20 | void TokensMaster_Serializer::bind(TokensMaster& tokens) { 21 | tokens_ = reinterpret_cast(&tokens.tokens_); 22 | holders_ = reinterpret_cast(&tokens.holders_); 23 | csdebug() << "TokensMaster bindings made"; 24 | } 25 | 26 | void TokensMaster_Serializer::clear(const std::filesystem::path& rootDir) { 27 | tokens_->clear(); 28 | holders_->clear(); 29 | save(rootDir); 30 | } 31 | 32 | void TokensMaster_Serializer::save(const std::filesystem::path& rootDir) { 33 | std::ofstream ofs(rootDir / kDataFileName); 34 | boost::archive::text_oarchive oa(ofs); 35 | oa << *tokens_; 36 | oa << *holders_; 37 | } 38 | 39 | ::cscrypto::Hash TokensMaster_Serializer::hash() { 40 | { 41 | std::ofstream ofs(kDataFileName); 42 | boost::archive::text_oarchive oa( 43 | ofs, 44 | boost::archive::no_header | boost::archive::no_codecvt 45 | ); 46 | std::map tmp_tokens( 47 | tokens_->begin(), 48 | tokens_->end() 49 | ); 50 | std::map> tmp_holders( 51 | holders_->begin(), 52 | holders_->end() 53 | ); 54 | oa << tmp_tokens; 55 | oa << tmp_holders; 56 | } 57 | auto result = SerializersHelper::getHashFromFile(kDataFileName); 58 | std::filesystem::remove(kDataFileName); 59 | return result; 60 | } 61 | 62 | void TokensMaster_Serializer::load(const std::filesystem::path& rootDir) { 63 | std::ifstream ifs(rootDir / kDataFileName); 64 | boost::archive::text_iarchive ia(ifs); 65 | ia >> *tokens_; 66 | ia >> *holders_; 67 | } 68 | } // namespace cs 69 | -------------------------------------------------------------------------------- /csnode/src/walletsids_serializer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //#include 6 | //#include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "logger.hpp" 16 | 17 | namespace { 18 | const std::string kDataFileName = "walletsids.dat"; 19 | } // namespace 20 | 21 | namespace cs { 22 | void WalletsIds_Serializer::bind(WalletsIds& ids) { 23 | data_ = reinterpret_cast(&ids.data_); 24 | nextId_ = &ids.nextId_; 25 | csdebug() << "WalletsIds bindings made"; 26 | } 27 | 28 | void WalletsIds_Serializer::clear(const std::filesystem::path& rootDir) { 29 | data_->clear(); 30 | *nextId_ = 0; 31 | save(rootDir); 32 | } 33 | 34 | void WalletsIds_Serializer::save(const std::filesystem::path& rootDir) { 35 | std::ofstream ofs(rootDir / kDataFileName, std::ios::binary); 36 | boost::archive::binary_oarchive oa(ofs); 37 | oa << *data_; 38 | oa << *nextId_; 39 | } 40 | 41 | ::cscrypto::Hash WalletsIds_Serializer::hash() { 42 | { 43 | std::ofstream ofs(kDataFileName, std::ios::binary); 44 | boost::archive::binary_oarchive oa( 45 | ofs, 46 | boost::archive::no_header | boost::archive::no_codecvt 47 | ); 48 | auto& data_ref = data_->get<0>(); 49 | std::vector data( 50 | data_ref.begin(), 51 | data_ref.end() 52 | ); 53 | std::sort( 54 | data.begin(), 55 | data.end(), 56 | [](const Wallet& l, const Wallet& r) { return l.address < r.address; } 57 | ); 58 | oa << data; 59 | oa << *nextId_; 60 | } 61 | auto result = SerializersHelper::getHashFromFile(kDataFileName); 62 | std::filesystem::remove(kDataFileName); 63 | return result; 64 | } 65 | 66 | void WalletsIds_Serializer::load(const std::filesystem::path& rootDir) { 67 | std::ifstream ifs(rootDir / kDataFileName, std::ios::binary); 68 | boost::archive::binary_iarchive ia(ifs); 69 | ia >> *data_; 70 | ia >> *nextId_; 71 | } 72 | } // namespace cs 73 | -------------------------------------------------------------------------------- /csnode/src/walletsstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cs { 4 | 5 | WalletsState::WalletData& WalletsState::getData(const WalletAddress& address) { 6 | auto pubKey = wallCache_.toPublicKey(address); 7 | auto it = storage_.find(pubKey); 8 | if (it != storage_.end()) { 9 | return it->second; 10 | } 11 | else { 12 | auto walletPtr = wallCache_.findWallet(address); 13 | if (walletPtr) { 14 | auto res = storage_.insert(std::make_pair(pubKey, 15 | WalletData{noInd_, 16 | walletPtr->balance_, 17 | walletPtr->delegated_, 18 | walletPtr->delegateSources_ ? *walletPtr->delegateSources_ : std::map>{},// accounts, delegated to current account 19 | walletPtr->delegateTargets_ ? *walletPtr->delegateTargets_ : std::map>{},// accounts to which current round delegated special amounts 20 | walletPtr->trxTail_})); 21 | return res.first->second; 22 | } 23 | else { 24 | auto res = storage_.insert(std::make_pair(pubKey, WalletData{noInd_})); 25 | return res.first->second; 26 | } 27 | } 28 | } 29 | } // namespace cs 30 | -------------------------------------------------------------------------------- /dbsql/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | 3 | project(dbsql) 4 | 5 | add_library(${PROJECT_NAME} STATIC 6 | src/pgbackend.cpp 7 | src/pgbackend.h 8 | src/pgconnection.cpp 9 | src/pgconnection.h 10 | src/roundinfo.cpp 11 | include/dbsql/roundinfo.hpp 12 | ) 13 | 14 | configure_msvc_flags() 15 | 16 | find_package(PostgreSQL REQUIRED) 17 | 18 | target_include_directories(${PROJECT_NAME} PRIVATE ${PostgreSQL_INCLUDE_DIRS}) 19 | 20 | target_include_directories( 21 | ${PROJECT_NAME} PUBLIC 22 | ${CMAKE_CURRENT_SOURCE_DIR}/include 23 | ) 24 | 25 | target_link_libraries(${PROJECT_NAME} PRIVATE lib cscrypto csnode ${PostgreSQL_LIBRARIES}) 26 | 27 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) 28 | set_property(TARGET ${PROJECT_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 29 | -------------------------------------------------------------------------------- /dbsql/include/dbsql/roundinfo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ROUNDINFO_H 2 | #define ROUNDINFO_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace dbsql { 10 | void saveConfidants(uint64_t round, const std::vector& confidants, uint64_t mask); 11 | } 12 | 13 | #endif // ROUNDINFO_H 14 | -------------------------------------------------------------------------------- /dbsql/src/pgbackend.cpp: -------------------------------------------------------------------------------- 1 | #include "pgbackend.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace dbsql { 9 | PGBackend::PGBackend() { 10 | createPool(); 11 | } 12 | 13 | void PGBackend::createPool() { 14 | std::lock_guard lock_(mutex_); 15 | 16 | for (auto i = 0; i < POOL; ++i) { 17 | pool_.emplace(std::make_shared()); 18 | } 19 | } 20 | 21 | std::shared_ptr PGBackend::connection() { 22 | std::unique_lock lock_(mutex_); 23 | 24 | while (pool_.empty()) { 25 | condition_.wait(lock_); 26 | } 27 | 28 | auto conn_ = pool_.front(); 29 | pool_.pop(); 30 | 31 | return conn_; 32 | } 33 | 34 | void PGBackend::freeConnection(std::shared_ptr conn_) { 35 | std::unique_lock lock_(mutex_); 36 | 37 | pool_.push(conn_); 38 | lock_.unlock(); 39 | condition_.notify_one(); 40 | } 41 | 42 | int sendQuery(std::shared_ptr conn, std::string& query) { 43 | PQsendQuery(conn->connection().get(), query.c_str()); 44 | while (auto res = PQgetResult(conn->connection().get())) { 45 | PQclear(res); 46 | } 47 | return 0; 48 | } 49 | 50 | PGBackend& PGBackend::instance() { 51 | static PGBackend instance; 52 | return instance; 53 | } 54 | } // namespacce bdsql 55 | -------------------------------------------------------------------------------- /dbsql/src/pgbackend.h: -------------------------------------------------------------------------------- 1 | #ifndef PGBACKEND_H 2 | #define PGBACKEND_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "pgconnection.h" 12 | 13 | namespace dbsql { 14 | class PGBackend { 15 | public: 16 | PGBackend(); 17 | std::shared_ptr connection(); 18 | void freeConnection(std::shared_ptr); 19 | 20 | static PGBackend& instance(); 21 | private: 22 | void createPool(); 23 | 24 | std::mutex mutex_; 25 | std::condition_variable condition_; 26 | std::queue> pool_; 27 | 28 | static constexpr int POOL = 10; 29 | }; 30 | 31 | int sendQuery(std::shared_ptr conn, std::string& query); 32 | } // namespace dbsql 33 | 34 | #endif // PGBACKEND_H 35 | -------------------------------------------------------------------------------- /dbsql/src/pgconnection.cpp: -------------------------------------------------------------------------------- 1 | #include "pgconnection.h" 2 | 3 | #include 4 | 5 | namespace dbsql { 6 | PGConnection::PGConnection() { 7 | auto conf = Config::get(); 8 | 9 | connection_.reset(PQsetdbLogin(conf.dbhost.c_str(), std::to_string(conf.dbport).c_str(), 10 | nullptr, nullptr, conf.dbname.c_str(), conf.dbuser.c_str(), conf.dbpassword.c_str()), &PQfinish); 11 | 12 | if (PQstatus(connection_.get()) != CONNECTION_OK && 13 | PQsetnonblocking(connection_.get(), 1) != 0) { 14 | throw std::runtime_error(PQerrorMessage(connection_.get())); 15 | } 16 | } 17 | 18 | std::shared_ptr PGConnection::connection() const { 19 | return connection_; 20 | } 21 | 22 | PGConnection::Config::Config() { 23 | auto csconfig = cs::ConfigHolder::instance().config()->getDbSQLData(); 24 | 25 | dbhost = csconfig.host; 26 | dbport = csconfig.port; 27 | dbname = csconfig.name; 28 | dbuser = csconfig.user; 29 | dbpassword = csconfig.password; 30 | } 31 | 32 | PGConnection::Config& PGConnection::Config::get() { 33 | static PGConnection::Config instance; 34 | return instance; 35 | } 36 | } // namespace dbsql 37 | -------------------------------------------------------------------------------- /dbsql/src/pgconnection.h: -------------------------------------------------------------------------------- 1 | #ifndef PGCONNECTION_H 2 | #define PGCONNECTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace dbsql { 11 | class PGConnection { 12 | public: 13 | PGConnection(); 14 | 15 | std::shared_ptr connection() const; 16 | private: 17 | void establish_connection(); 18 | 19 | struct Config { 20 | Config(); 21 | 22 | std::string dbhost; 23 | int dbport; 24 | std::string dbname; 25 | std::string dbuser; 26 | std::string dbpassword; 27 | 28 | static Config& get(); 29 | }; 30 | 31 | std::shared_ptr connection_; 32 | }; 33 | } // namespace dbsql 34 | 35 | #endif // PGCONNECTION_H 36 | -------------------------------------------------------------------------------- /dbsql/src/roundinfo.cpp: -------------------------------------------------------------------------------- 1 | #include "pgbackend.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace dbsql { 7 | void saveConfidants(uint64_t round, const std::vector& confidants, uint64_t mask) { 8 | auto conn = PGBackend::instance().connection(); 9 | 10 | int index = 0; 11 | for(auto& pkey: confidants) { 12 | auto pk58 = EncodeBase58(pkey.data(), pkey.data() + pkey.size()); 13 | std::string trusted = mask & (1 << index++) ? "'t'" : "'f'"; 14 | std::string query; 15 | query = "INSERT INTO public_keys(public_key)" 16 | "SELECT'" + pk58 + "'" 17 | "WHERE" 18 | " NOT EXISTS (" 19 | " SELECT public_key FROM public_keys WHERE public_key = '" + pk58 + "'" 20 | " )"; 21 | sendQuery(conn, query); 22 | 23 | query = "INSERT INTO round_info(round_num, public_id, real_trusted)" 24 | "VALUES(" + std::to_string(round) + 25 | ", (SELECT id from public_keys WHERE public_key='" + pk58 + "')" 26 | ", " + trusted + ")"; 27 | sendQuery(conn, query); 28 | } 29 | PGBackend::instance().freeConnection(conn); 30 | } 31 | } // namespace dbsql 32 | -------------------------------------------------------------------------------- /dbsql/src/roundinfo.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE DATABASE roundinfo WITH TEMPLATE = template0; 3 | 4 | ALTER DATABASE roundinfo OWNER TO postgres; 5 | 6 | \connect roundinfo 7 | 8 | CREATE TABLE public_keys ( 9 | id serial PRIMARY KEY, 10 | public_key character(44) NOT NULL UNIQUE 11 | ); 12 | 13 | ALTER TABLE public_keys OWNER TO postgres; 14 | 15 | CREATE TABLE round_info ( 16 | round_num bigint NOT NULL, 17 | public_id integer NOT NULL REFERENCES public_keys ON DELETE RESTRICT, 18 | real_trusted BOOLEAN DEFAULT true 19 | ); 20 | 21 | ALTER TABLE round_info OWNER TO postgres; 22 | -------------------------------------------------------------------------------- /example/config.ini: -------------------------------------------------------------------------------- 1 | [params] 2 | node_type=client 3 | bootstrap_type=list 4 | hosts_filename=hosts.txt 5 | 6 | [signal_server] 7 | ip=fe80::46f6:1a3f:edf5:371a 8 | port=7776 9 | 10 | [host_input] 11 | ip=127.0.0.1 12 | port=9000 13 | 14 | [host_output] 15 | ip=192.168.0.1 16 | port=9001 17 | 18 | [host_address] 19 | ip=192.168.0.1 20 | port=9008 21 | -------------------------------------------------------------------------------- /example/credits.node.systemd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Credits blockchain node service 3 | After=network-online.target syslog.target 4 | 5 | [Service] 6 | LimitCORE=infinity 7 | Type=forking 8 | EnvironmentFile=${ENV_FILE} 9 | User=${USER} 10 | Group=${GROUP} 11 | ExecStart=${CREDITSHOME}/bin/node --working_dir=${CREDITSHOME} 12 | PIDFile=${CREDITSHOME}/credits_node.pid 13 | Restart=on-abnormal 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /example/hosts.txt: -------------------------------------------------------------------------------- 1 | 10.200.1.12:312 2 | 12.11.123.222:1111 3 | [2001:db8:85a3:8d3:1319:8a2e:370:7348]:12 4 | [fe80::1ff:fe23:4567:890a]:443 5 | -------------------------------------------------------------------------------- /example/new/PublicKey.txt: -------------------------------------------------------------------------------- 1 | EMKVo1QadgByNZAzLDsByyK4CG5ZmBYADY4VzspnY3GF -------------------------------------------------------------------------------- /example/new/config.ini: -------------------------------------------------------------------------------- 1 | [params] 2 | node_type=client 3 | bootstrap_type=signal_server 4 | ipv6=false 5 | 6 | [signal_server] 7 | ip=192.168.0.198 8 | port=6000 9 | 10 | [host_input] 11 | port=9000 12 | key=fe80::dd6a:3c42:8823:7413 -------------------------------------------------------------------------------- /example/new/hosts.txt: -------------------------------------------------------------------------------- 1 | 10.200.1.12:312 2 | 12.11.123.222:1111 3 | [2001:db8:85a3:8d3:1319:8a2e:370:7348]:12 4 | [fe80::1ff:fe23:4567:890a]:443 5 | -------------------------------------------------------------------------------- /js-client/api_test.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /js-client/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PATH=$PATH:third-party/thrift/compiler/msvc/ 3 | thrift --gen js -out js-client/js third-party/thrift-interface-definitions/api.thrift 4 | thrift --gen js -out js-client/js third-party/thrift-interface-definitions/variant.thrift 5 | -------------------------------------------------------------------------------- /lib/include/lib/system/cache.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CACHE_HPP 2 | #define CACHE_HPP 3 | 4 | #include 5 | 6 | #ifdef __cpp_lib_hardware_interference_size 7 | constexpr unsigned kCacheLineSize = std::hardware_constructive_interference_size; 8 | #else 9 | constexpr unsigned kCacheLineSize = 64; 10 | #endif 11 | 12 | #define __cacheline_aligned alignas(kCacheLineSize) 13 | 14 | #endif // CACHE_HPP 15 | -------------------------------------------------------------------------------- /lib/include/lib/system/console.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONSOLE_HPP 2 | #define CONSOLE_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace cs { 10 | namespace cshelper { 11 | template 12 | void print(const T& container, std::false_type) { 13 | for (const auto& element : container) { 14 | std::cout << element << " "; 15 | } 16 | } 17 | 18 | template 19 | void print(const T& container, std::true_type) { 20 | for (const auto& [key, value] : container) { 21 | std::cout << "[Key " << key << ", value " << value << "] "; 22 | } 23 | 24 | std::cout << std::endl; 25 | } 26 | } // namespace cshelper 27 | 28 | class Console { 29 | public: 30 | template 31 | static void write(Args&&... args) { 32 | (std::cout << ... << std::forward(args)); 33 | } 34 | 35 | template 36 | static void writeLine(Args&&... args) { 37 | (std::cout << ... << std::forward(args)) << std::endl; 38 | } 39 | 40 | template 41 | static void print(const T& container) { 42 | cshelper::print(container, cs::IsPair()); 43 | } 44 | 45 | template 46 | static void writeLineSync(Args&&... args) { 47 | std::stringstream ss; 48 | (ss << ... << std::forward(args)) << std::endl; 49 | 50 | std::cout << ss.str(); 51 | } 52 | }; 53 | } // namespace cs 54 | 55 | #endif // CONSOLE_HPP 56 | -------------------------------------------------------------------------------- /lib/include/lib/system/dynamicbuffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DYNAMICBUFFER_HPP 2 | #define DYNAMICBUFFER_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace csval { 8 | const std::size_t defaultSize = 5000; 9 | } 10 | 11 | namespace cs { 12 | /// 13 | /// RAII fixed dynamic memory c-array wrapper 14 | /// 15 | class DynamicBuffer final { 16 | public: 17 | explicit DynamicBuffer(std::size_t size = csval::defaultSize); 18 | explicit DynamicBuffer(const char* data, std::size_t size); 19 | explicit DynamicBuffer(const unsigned char* data, std::size_t size); 20 | 21 | DynamicBuffer(const DynamicBuffer& buffer); 22 | DynamicBuffer(DynamicBuffer&& buffer); 23 | 24 | DynamicBuffer& operator=(const DynamicBuffer& buffer); 25 | DynamicBuffer& operator=(DynamicBuffer&& buffer); 26 | 27 | ~DynamicBuffer(); 28 | 29 | char& operator[](std::size_t index); 30 | const char& operator[](std::size_t index) const; 31 | 32 | /// 33 | /// Returns pointer to c-array 34 | /// 35 | char* get() const; 36 | 37 | /// 38 | /// get() method similar 39 | /// 40 | char* operator*() const; 41 | 42 | /// 43 | /// Returns c-array fixed size 44 | /// 45 | std::size_t size() const; 46 | 47 | // stl - like interace 48 | char* begin(); 49 | char* end(); 50 | const char* begin() const; 51 | const char* end() const; 52 | 53 | private: 54 | char* array_ = nullptr; 55 | std::size_t size_ = 0; 56 | 57 | friend void swap(DynamicBuffer&, DynamicBuffer&); 58 | }; 59 | 60 | bool operator==(const DynamicBuffer& lhs, const DynamicBuffer& rhs); 61 | bool operator!=(const DynamicBuffer& lhs, const DynamicBuffer& rhs); 62 | 63 | void swap(DynamicBuffer& lhs, DynamicBuffer& rhs); 64 | 65 | /// 66 | /// Smart dynamic buffer 67 | /// 68 | using DynamicBufferPtr = std::shared_ptr; 69 | } // namespace cs 70 | 71 | #endif // DYNAMICBUFFER_HPP 72 | -------------------------------------------------------------------------------- /lib/include/lib/system/fileutils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FILEUTILS_HPP 2 | #define FILEUTILS_HPP 3 | 4 | #ifdef _MSC_VER 5 | #pragma warning(push, 0) 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | #ifdef _MSC_VER 12 | #pragma warning(pop) 13 | #endif 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace cs { 22 | class FileUtils { 23 | public: 24 | static bool isPathExist(const std::string& path) { 25 | namespace fs = boost::filesystem; 26 | 27 | fs::path p(path); 28 | bool res = false; 29 | 30 | try { 31 | res = fs::is_directory(p); 32 | } 33 | catch (const std::exception& e) { 34 | cs::Console::writeLine(funcName(), ", ", e.what()); 35 | } 36 | 37 | return res; 38 | } 39 | 40 | static bool createPath(const std::string& path) { 41 | namespace fs = boost::filesystem; 42 | 43 | fs::path p(path); 44 | bool res = false; 45 | 46 | try { 47 | res = fs::create_directory(p); 48 | } 49 | catch (const std::exception& e) { 50 | cs::Console::writeLine(funcName(), ", ", e.what()); 51 | } 52 | 53 | return res; 54 | } 55 | 56 | static bool createPathIfNoExist(const std::string& path) { 57 | if (isPathExist(path)) { 58 | return true; 59 | } 60 | 61 | return createPath(path); 62 | } 63 | 64 | static cs::Bytes readAllFileData(const std::string& fileName) { 65 | std::ifstream file(fileName); 66 | return cs::Bytes((std::istreambuf_iterator(file)), std::istreambuf_iterator()); 67 | } 68 | 69 | static bool isFileExists(const std::string& fileName) { 70 | namespace fs = boost::filesystem; 71 | 72 | boost::system::error_code code; 73 | return fs::exists(fileName, code); 74 | } 75 | 76 | static bool removePath(const std::string& pathName) { 77 | namespace fs = boost::filesystem; 78 | 79 | fs::path path(pathName); 80 | bool res = false; 81 | 82 | try { 83 | res = fs::remove_all(path); 84 | } 85 | catch (const std::exception& e) { 86 | cs::Console::writeLine(funcName(), ", ", e.what()); 87 | } 88 | 89 | return res; 90 | } 91 | }; 92 | } 93 | 94 | #endif // FILEUTILS_HPP 95 | -------------------------------------------------------------------------------- /lib/include/lib/system/hash.hpp: -------------------------------------------------------------------------------- 1 | /* Send blaming letters to @yrtimd */ 2 | #ifndef HASH_HPP 3 | #define HASH_HPP 4 | 5 | #include 6 | #include "utils.hpp" 7 | 8 | inline cs::Hash generateHash(const void* data, size_t length) { 9 | return cscrypto::calculateHash(reinterpret_cast(data), length); 10 | } 11 | 12 | template <> 13 | inline uint16_t getHashIndex(const cs::Hash& hash) { 14 | constexpr const size_t border = kHashLength / 2; 15 | 16 | uint16_t result = 0; 17 | auto byte = reinterpret_cast(&result); 18 | 19 | for (size_t i = 0; i < border; ++i) { 20 | *byte ^= hash[i]; 21 | } 22 | 23 | ++byte; 24 | 25 | for (size_t i = border; i < kHashLength; ++i) { 26 | *byte ^= hash[i]; 27 | } 28 | 29 | return result; 30 | } 31 | 32 | template <> 33 | inline uint32_t getHashIndex(const cs::Hash& hash) { 34 | return *reinterpret_cast(hash.data()); 35 | } 36 | 37 | template <> 38 | inline std::size_t getHashIndex(const cs::Hash& hash) { 39 | return *reinterpret_cast(hash.data()); 40 | } 41 | 42 | template 43 | uint32_t MurmurHash2(const uint8_t* key) { 44 | constexpr uint32_t m = 0x5bd1e995; 45 | constexpr uint32_t seed = 0; 46 | constexpr int r = 24; 47 | 48 | unsigned int h = seed ^ N; 49 | 50 | const uint8_t* data = key; 51 | unsigned int k; 52 | 53 | size_t len = N; 54 | while (len >= 4) 55 | { 56 | k = data[0]; 57 | k |= data[1] << 8; 58 | k |= data[2] << 16; 59 | k |= data[3] << 24; 60 | 61 | k *= m; 62 | k ^= k >> r; 63 | k *= m; 64 | 65 | h *= m; 66 | h ^= k; 67 | 68 | data += 4; 69 | len -= 4; 70 | } 71 | 72 | switch (len) 73 | { 74 | case 3: 75 | h ^= data[2] << 16; 76 | case 2: 77 | h ^= data[1] << 8; 78 | case 1: 79 | h ^= data[0]; 80 | h *= m; 81 | }; 82 | 83 | h ^= h >> 13; 84 | h *= m; 85 | h ^= h >> 15; 86 | 87 | return h; 88 | } 89 | 90 | #endif // HASH_HPP 91 | -------------------------------------------------------------------------------- /lib/include/lib/system/lockfreechanger.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOCKFREE_CHANGER_HPP 2 | #define LOCKFREE_CHANGER_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace cs { 10 | template 11 | class LockFreeChanger { 12 | public: 13 | LockFreeChanger() 14 | : data_(std::make_shared()) { 15 | } 16 | 17 | template 18 | explicit LockFreeChanger(Args&&... value) 19 | : data_(std::make_shared(std::forward(value)...)) { 20 | } 21 | 22 | LockFreeChanger(const LockFreeChanger&) = delete; 23 | LockFreeChanger& operator=(const LockFreeChanger&) = delete; 24 | 25 | template 26 | void exchange(Args&&... value) const { 27 | std::shared_ptr newValue = std::make_shared(std::forward(value)...); 28 | std::shared_ptr current; 29 | 30 | do { 31 | current = data_; 32 | } 33 | while (!std::atomic_compare_exchange_weak_explicit(&data_, ¤t, newValue, std::memory_order_release, 34 | std::memory_order_relaxed)); 35 | } 36 | 37 | T* operator->() { 38 | return data_.get(); 39 | } 40 | 41 | const T* operator->() const { 42 | return data_.get(); 43 | } 44 | 45 | T operator*() const { 46 | return *(data_.get()); 47 | } 48 | 49 | T data() const { 50 | return this->operator*(); 51 | } 52 | 53 | private: 54 | __cacheline_aligned mutable std::shared_ptr data_; 55 | }; 56 | } 57 | 58 | #endif // LOCKFREE_CHANGER_HPP 59 | -------------------------------------------------------------------------------- /lib/include/lib/system/mmappedfile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MMAPPEDFILE_H 2 | #define MMAPPEDFILE_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace cs { 11 | using FileSource = boost::iostreams::mapped_file_source; 12 | using FileSink = boost::iostreams::mapped_file_sink; 13 | 14 | template 15 | class MMappedFileWrap { 16 | public: 17 | MMappedFileWrap(const std::string& path, 18 | size_t maxSize = boost::iostreams::mapped_file::max_length, 19 | bool createNew = true) { 20 | try { 21 | if (!createNew) { 22 | file_.open(path, maxSize); 23 | } 24 | else { 25 | boost::iostreams::mapped_file_params params; 26 | params.path = path; 27 | params.new_file_size = maxSize; 28 | file_.open(params); 29 | } 30 | } 31 | catch (std::exception& e) { 32 | cserror() << e.what(); 33 | } 34 | catch (...) { 35 | cserror() << __FILE__ << ", " 36 | << __LINE__ 37 | << " exception ..."; 38 | } 39 | } 40 | 41 | bool isOpen() { 42 | return file_.is_open(); 43 | } 44 | 45 | ~MMappedFileWrap() { 46 | if (isOpen()) { 47 | file_.close(); 48 | } 49 | } 50 | 51 | template 52 | T* data() { 53 | return isOpen() ? (T*)file_.data() : nullptr; 54 | } 55 | 56 | private: 57 | BoostMMapedFile file_; 58 | }; 59 | } // namespace cs 60 | #endif // MMAPPEDFILE_H 61 | -------------------------------------------------------------------------------- /lib/include/lib/system/pmrfactory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PMRFACTORY_HPP 2 | #define PMRFACTORY_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cs { 9 | class PmrFactory { 10 | public: 11 | template 12 | static cs::PmrBytes bytes(const cs::PmrAllocator& allocator) { 13 | #ifdef __cpp_lib_memory_resource 14 | using Allocator = cs::PmrBytes::allocator_type; 15 | return cs::PmrBytes(Allocator(allocator.resource())); 16 | #else 17 | csunused(allocator); 18 | return cs::PmrBytes{}; 19 | #endif 20 | } 21 | }; 22 | } // namespace cs 23 | 24 | #endif // PMRFACTORY_HPP 25 | -------------------------------------------------------------------------------- /lib/include/lib/system/processexception.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROCESSEXCEPTION_HPP 2 | #define PROCESSEXCEPTION_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace cs { 8 | class ProcessException : public std::exception { 9 | public: 10 | explicit ProcessException(const std::string& message, int code = 0) 11 | : message_(message) 12 | , code_(code) { 13 | } 14 | 15 | ProcessException(const ProcessException&) = default; 16 | ProcessException(ProcessException&&) = default; 17 | 18 | virtual const char* what() const noexcept override { 19 | return message_.c_str(); 20 | } 21 | 22 | int code() const { 23 | return code_; 24 | } 25 | 26 | private: 27 | std::string message_; 28 | int code_ = 0; 29 | }; 30 | } 31 | 32 | #endif // PROCESSEXCEPTION_HPP 33 | -------------------------------------------------------------------------------- /lib/include/lib/system/progressbar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROGRESSBAR_HPP 2 | #define PROGRESSBAR_HPP 3 | 4 | #include 5 | 6 | class ProgressBar { 7 | using Progress = unsigned int; 8 | 9 | public: 10 | ProgressBar(const ProgressBar&) = default; 11 | ProgressBar(ProgressBar&&) = default; 12 | ProgressBar& operator=(const ProgressBar&) = default; 13 | ProgressBar& operator=(ProgressBar&&) = default; 14 | 15 | /// @brief ProgressBar 16 | /// @param completeSymbol symbol that mark completed progress 17 | /// @param incompleteSymbol symbol that mark incompleted bar ticks 18 | /// @param totalProgressLimit in other words total progress percentage of completion 19 | /// @param barWidthInSymbols displayed real width of progress bar in symbols 20 | explicit ProgressBar(char completeSymbol = '#', char incompleteSymbol = '_', unsigned totalProgressLimit = 100, unsigned barWidthInSymbols = 50); 21 | ~ProgressBar(); 22 | 23 | /// @brief string 24 | /// @param ticks current completed progress in ticks 25 | /// @return symbolic (std::string) progress representation 26 | std::string string(Progress ticks); 27 | 28 | char completeSymbol; 29 | char incompleteSymbol; 30 | Progress totalTicks; 31 | Progress barWidth; 32 | }; 33 | 34 | #endif // PROGRESSBAR_HPP 35 | -------------------------------------------------------------------------------- /lib/include/lib/system/reference.hpp: -------------------------------------------------------------------------------- 1 | #ifndef REFERENCE_HPP 2 | #define REFERENCE_HPP 3 | 4 | #include 5 | 6 | namespace cs { 7 | template 8 | class Reference { 9 | public: 10 | template 11 | Reference(const Reference& ref) 12 | : reference_(ref.reference_) { 13 | } 14 | 15 | T* operator->() const { 16 | return &reference_.get(); 17 | } 18 | 19 | operator T&() const { 20 | return reference_.get(); 21 | } 22 | 23 | static Reference make(T& value) { 24 | if constexpr (std::is_const_v) { 25 | return Reference{std::cref(value)}; 26 | } 27 | else { 28 | return Reference{std::ref(value)}; 29 | } 30 | } 31 | 32 | private: 33 | explicit Reference(const std::reference_wrapper& value) 34 | : reference_(value) { 35 | } 36 | 37 | std::reference_wrapper reference_; 38 | 39 | template 40 | friend class Reference; 41 | }; 42 | 43 | template 44 | Reference makeReference(T& value) noexcept { 45 | return Reference::make(value); 46 | } 47 | 48 | template 49 | Reference makeReference(T* value) noexcept { 50 | return makeReference(*value); 51 | } 52 | } 53 | 54 | #endif // REFERENCE_HPP 55 | -------------------------------------------------------------------------------- /lib/include/lib/system/scopeguard.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SCOPE_GUARD_HPP 2 | #define SCOPE_GUARD_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace cs { 8 | struct ScopeGuardBase { 9 | ScopeGuardBase() 10 | : isActive_(true) { 11 | } 12 | 13 | ScopeGuardBase(ScopeGuardBase&& rhs) 14 | : isActive_(rhs.isActive_) { 15 | rhs.dismiss(); 16 | } 17 | 18 | void dismiss() noexcept { 19 | isActive_ = false; 20 | } 21 | 22 | protected: 23 | ~ScopeGuardBase() = default; 24 | bool isActive_; 25 | }; 26 | 27 | template 28 | struct ScopeGuard : public ScopeGuardBase { 29 | ScopeGuard() = delete; 30 | ScopeGuard(const ScopeGuard&) = delete; 31 | 32 | ScopeGuard(Func f) noexcept 33 | : ScopeGuardBase() 34 | , func_(std::move(f)) { 35 | } 36 | 37 | ScopeGuard(ScopeGuard&& rhs) noexcept 38 | : ScopeGuardBase(std::move(rhs)) 39 | , func_(std::move(rhs.func_)) { 40 | } 41 | 42 | ~ScopeGuard() noexcept { 43 | if (isActive_) { 44 | try { 45 | func_(); 46 | } 47 | catch (...) { 48 | cserror() << "Scope guard callable exception, " << typeid(Func).name() << " func type"; 49 | } 50 | } 51 | } 52 | 53 | ScopeGuard& operator=(const ScopeGuard&) = delete; 54 | 55 | private: 56 | Func func_; 57 | }; 58 | 59 | template 60 | ScopeGuard scopeGuard(Fun f) { 61 | return ScopeGuard(std::move(f)); 62 | } 63 | } // namespace cs 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /lib/include/lib/system/serialize_tuple.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace boost { 7 | namespace serialization { 8 | 9 | template 10 | struct Serialize 11 | { 12 | template 13 | static void serialize(Archive & ar, std::tuple & t, const unsigned int version) 14 | { 15 | ar & std::get(t); 16 | Serialize::serialize(ar, t, version); 17 | } 18 | }; 19 | 20 | template<> 21 | struct Serialize<0> 22 | { 23 | template 24 | static void serialize(Archive & ar, std::tuple & t, const unsigned int version) 25 | { 26 | (void) ar; 27 | (void) t; 28 | (void) version; 29 | } 30 | }; 31 | 32 | template 33 | void serialize(Archive & ar, std::tuple & t, const unsigned int version) 34 | { 35 | Serialize::serialize(ar, t, version); 36 | } 37 | 38 | } // namespace boost 39 | } // namespace serialization 40 | -------------------------------------------------------------------------------- /lib/include/lib/system/service/service.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | #include "win_service.hpp" 5 | #include "win_install.hpp" 6 | #else 7 | #include "unix_service.hpp" 8 | #endif 9 | 10 | #include "service_owner.hpp" 11 | -------------------------------------------------------------------------------- /lib/include/lib/system/service/service_owner.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _WIN32 4 | #include 5 | #endif // !_WIN32 6 | 7 | namespace cs { 8 | 9 | class ServiceOwner { 10 | public: 11 | virtual bool onInit(const char*) { return true; } 12 | virtual bool onRun(const char*) = 0; 13 | virtual bool onStop() = 0; 14 | #ifndef _WIN32 15 | virtual bool onFork(const char*, pid_t) { return true; } 16 | #endif // !_WIN32 17 | virtual bool onPause() { return true; } 18 | virtual bool onContinue() { return true; } 19 | virtual bool onParamChange() { return true; } 20 | virtual bool onException() noexcept { return true; } 21 | #ifdef _WIN32 22 | #if (_WIN32_WINNT >= _WIN32_WINNT_WINXP) 23 | virtual bool onSessionChanged(int /* what */, void* /* info */) { return true; } 24 | virtual bool onDeviceEvent(int /* what */, void* /* info */) { return true; } 25 | #endif // _WIN32_WINNT >= _WIN32_WINNT_WINXP 26 | #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) 27 | virtual bool onPreshutdown() { return true; } 28 | #endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA 29 | #endif // _WIN32 30 | 31 | virtual ~ServiceOwner() = default; 32 | }; 33 | 34 | } // namespace cs 35 | -------------------------------------------------------------------------------- /lib/include/lib/system/shareable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SHAREABLE_HPP 2 | #define SHAREABLE_HPP 3 | 4 | #include 5 | 6 | namespace cs { 7 | // CRTP idiome 8 | template 9 | class Shareable { 10 | public: 11 | using Type = T; 12 | using SharedPointer = std::shared_ptr; 13 | 14 | template 15 | static SharedPointer createShareable(Args&&... args) { 16 | return std::make_shared(std::forward(args)...); 17 | } 18 | }; 19 | } 20 | 21 | #endif // SHAREABLE_HPP 22 | -------------------------------------------------------------------------------- /lib/include/lib/system/timer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TIMER_HPP 2 | #define TIMER_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace cs { 11 | using TimerCallbackSignature = void(); 12 | using TimerCallback = std::function; 13 | using TimeOutSignal = cs::Signal; 14 | 15 | class Timer; 16 | 17 | /// 18 | /// Represents standard timer that calls callbacks every msec with time correction. 19 | /// @brief Timer emits time out signal by run policy. 20 | /// 21 | class Timer : public Shareable { 22 | public: 23 | enum : unsigned int { 24 | RangeDeltaInPercents = 10, 25 | HighPreciseTimerSleepTimeMs = 1 26 | }; 27 | 28 | enum class Type : cs::Byte { 29 | Standard, 30 | HighPrecise 31 | }; 32 | 33 | Timer(); 34 | ~Timer(); 35 | 36 | void start(int msec, Type type = Type::Standard, RunPolicy policy = RunPolicy::ThreadPolicy); 37 | void stop(); 38 | void restart(); 39 | 40 | bool isRunning() const; 41 | Type type() const; 42 | 43 | static void singleShot(int msec, cs::RunPolicy policy, TimerCallback callback); 44 | 45 | public signals: 46 | 47 | // generates when timer ticks 48 | TimeOutSignal timeOut; 49 | 50 | protected: 51 | // timer main loop 52 | void loop(); 53 | void preciseLoop(); 54 | 55 | // timer rehabilitation when timer degradate 56 | void rehabilitation(); 57 | void call(); 58 | 59 | private: 60 | bool isRunning_; 61 | bool isRehabilitation_; 62 | std::atomic interruption_; 63 | 64 | std::thread timerThread_; 65 | Type type_; 66 | std::atomic policy_; 67 | 68 | unsigned int allowDifference_; 69 | std::chrono::milliseconds ms_; 70 | std::atomic ns_; 71 | 72 | std::chrono::milliseconds realMs_; 73 | std::chrono::time_point rehabilitationStartValue_; 74 | }; 75 | } // namespace cs 76 | 77 | #endif // TIMER_HPP 78 | -------------------------------------------------------------------------------- /lib/src/lib/system/common.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t std::hash::operator()(const cs::PublicKey& key) const { 4 | static_assert(sizeof(size_t) < sizeof(cs::PublicKey)); 5 | 6 | size_t res; 7 | std::copy(key.data(), key.data() + sizeof(res), reinterpret_cast(&res)); 8 | 9 | return res; 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/lib/system/logger.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace logger { 10 | void initialize(const logging::settings& settings) { 11 | logging::add_common_attributes(); 12 | 13 | // formatters 14 | logging::register_simple_formatter_factory(logging::trivial::tag::severity::get_name()); 15 | // filters 16 | logging::register_simple_filter_factory(logging::trivial::tag::severity::get_name()); 17 | 18 | logging::init_from_settings(settings); 19 | } 20 | 21 | void cleanup() { 22 | logging::core::get()->remove_all_sinks(); 23 | } 24 | } // namespace logger 25 | -------------------------------------------------------------------------------- /lib/src/lib/system/progressbar.cpp: -------------------------------------------------------------------------------- 1 | #include "lib/system/progressbar.hpp" 2 | 3 | #include 4 | #include 5 | 6 | ProgressBar::ProgressBar(char completeSymbol, char incompleteSymbol, unsigned totalProgressLimit, unsigned barWidthInSymbols) 7 | : completeSymbol(completeSymbol) 8 | , incompleteSymbol(incompleteSymbol) 9 | , totalTicks(totalProgressLimit) 10 | , barWidth(barWidthInSymbols) { 11 | rang::setControlMode(rang::control::Force); 12 | rang::setWinTermMode(rang::winTerm::Ansi); 13 | #ifdef _WINDOWS 14 | // FIXME: it's a temporary hack to turn on ANSI sequences on windows terminal 15 | // because bar outputs progress to _any_ stream, so we need to force ansi 16 | rang::rang_implementation::setWinTermAnsiColors(std::cout.rdbuf()); 17 | #endif 18 | } 19 | 20 | ProgressBar::~ProgressBar() { 21 | rang::setControlMode(rang::control::Auto); 22 | rang::setWinTermMode(rang::winTerm::Auto); 23 | } 24 | 25 | std::string ProgressBar::string(ProgressBar::Progress ticks) { 26 | float progress = float(ticks) / totalTicks; 27 | auto pos = unsigned(barWidth * progress); 28 | 29 | std::string completed(pos, completeSymbol); 30 | std::string incompleted(barWidth - pos, incompleteSymbol); 31 | 32 | std::stringstream result; 33 | result << rang::bg::blue << rang::fg::blue << completed; 34 | result << rang::bg::gray << rang::fg::gray << incompleted; 35 | result << rang::bg::reset << rang::fg::reset << rang::style::reset; 36 | result << " " << (progress * 100.0f) << "%"; 37 | 38 | result.flush(); 39 | result << std::endl; 40 | 41 | return result.str(); 42 | } 43 | -------------------------------------------------------------------------------- /lmdbxx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(lmdbxx) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 8 | 9 | configure_msvc_flags() 10 | 11 | add_subdirectory(lmdb) 12 | 13 | add_library(${PROJECT_NAME} "./lmdbexception.hpp" 14 | "./lmdb.hpp" 15 | "./lmdb.cpp") 16 | 17 | target_include_directories(${PROJECT_NAME} PUBLIC "../third-party/lmdb/libraries/liblmdb/") 18 | target_include_directories(${PROJECT_NAME} PUBLIC "../third-party/lmdbxx/") 19 | target_include_directories(${PROJECT_NAME} PUBLIC "./" 20 | ${CMAKE_CURRENT_SOURCE_DIR}/../lib/include) 21 | 22 | target_link_libraries(${PROJECT_NAME} lmdb lib) 23 | -------------------------------------------------------------------------------- /lmdbxx/lmdb.cpp: -------------------------------------------------------------------------------- 1 | #include "lmdb.hpp" 2 | #include 3 | 4 | #include 5 | 6 | namespace fs = boost::filesystem; 7 | 8 | cs::Lmdb::Lmdb(const std::string& path, const unsigned int flags): path_(path), flags_(flags) { 9 | try { 10 | env_ = environment(flags); 11 | 12 | if (!cs::FileUtils::createPathIfNoExist(path_)) { 13 | std::cout << "Could not create path for Lmdb: " << path_ << std::endl; 14 | } 15 | } 16 | catch (const lmdb::error& error) { 17 | std::cout << "Lmdb construction error: " << error.what() << std::endl; 18 | } 19 | catch (const std::exception& e) { 20 | std::cout << "Lmdb construction error: " << e.what() << std::endl; 21 | } 22 | catch (...) { 23 | std::cout << "Lmdb unknown construction error\n"; 24 | } 25 | } 26 | 27 | cs::Lmdb::~Lmdb() noexcept { 28 | close(); 29 | } 30 | -------------------------------------------------------------------------------- /lmdbxx/lmdb/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(lmdb CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | configure_third_party_compiler_flags() 9 | 10 | add_library(${PROJECT_NAME} STATIC "../../third-party/lmdb/libraries/liblmdb/lmdb.h" 11 | "../../third-party/lmdb/libraries/liblmdb/mdb.c" 12 | "../../third-party/lmdb/libraries/liblmdb/mdb_copy.c" 13 | "../../third-party/lmdb/libraries/liblmdb/midl.h" 14 | "../../third-party/lmdb/libraries/liblmdb/midl.c") 15 | 16 | target_include_directories(${PROJECT_NAME} PUBLIC "../../third-party/lmdb/libraries/liblmdb/") 17 | -------------------------------------------------------------------------------- /lmdbxx/lmdbexception.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cs { 4 | class LmdbException : public lmdb::error { 5 | public: 6 | explicit LmdbException(const lmdb::error& error): lmdb::error(error) {} 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /net/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(net) 4 | 5 | add_library(net 6 | include/net/logger.hpp 7 | include/net/neighbourhood.hpp 8 | include/net/networkcommands.hpp 9 | include/net/packet.hpp 10 | include/net/packetvalidator.hpp 11 | include/net/packetsqueue.hpp 12 | include/net/transport.hpp 13 | src/neighbourhood.cpp 14 | src/networkcommands.cpp 15 | src/packet.cpp 16 | src/packetvalidator.cpp 17 | src/packetsqueue.cpp 18 | src/transport.cpp 19 | ) 20 | 21 | target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include 22 | ${CMAKE_CURRENT_SOURCE_DIR}/include/net) 23 | 24 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) 25 | set_property(TARGET ${PROJECT_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 26 | 27 | suppress_boost_cmake_warnings() 28 | configure_msvc_flags() 29 | 30 | target_link_libraries(${PROJECT_NAME} csnode lib cscrypto p2p_network csconnector) 31 | -------------------------------------------------------------------------------- /net/include/net/logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | //#define LOG_NET 11 | namespace logger { 12 | #ifndef LOG_NET 13 | using Net = None; 14 | #else 15 | BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS( 16 | Net, 17 | logging::sources::severity_channel_logger_mt, 18 | (logging::keywords::channel = "net") 19 | ); 20 | #endif // LOG_NET 21 | } // namespace logger 22 | -------------------------------------------------------------------------------- /net/include/net/networkcommands.hpp: -------------------------------------------------------------------------------- 1 | #ifndef NETWORKCOMMANDS_HPP 2 | #define NETWORKCOMMANDS_HPP 3 | 4 | #include 5 | 6 | enum class NetworkCommand : uint8_t { 7 | Error = 1, 8 | VersionRequest, 9 | VersionReply, 10 | Ping, 11 | Pong 12 | }; 13 | 14 | const char* networkCommandToString(NetworkCommand command); 15 | 16 | #endif // NETWORK_COMMANDS_HPP 17 | -------------------------------------------------------------------------------- /net/include/net/packetsqueue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PACKETS_QUEUE_HPP 2 | #define PACKETS_QUEUE_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "packet.hpp" 10 | 11 | class PacketsQueue { 12 | public: 13 | using SenderAndPacket = std::pair; 14 | 15 | bool empty() const; 16 | SenderAndPacket pop(); 17 | void push(const cs::PublicKey&, Packet&&); 18 | void clear(); 19 | private: 20 | enum class Priority { 21 | kFirst, 22 | kSecond 23 | }; 24 | 25 | Priority getPriority(MsgTypes type) const; 26 | size_t numPackets() const; 27 | size_t numBytes() const; 28 | bool shrink(); 29 | 30 | constexpr static size_t kMaxPacketsToHandle = 1ul << 17; // 131_072 31 | constexpr static size_t kMaxBytesToHandle = 1ul << 29; // 536_870_912 bytes 32 | 33 | size_t firstQBytes_ = 0; 34 | size_t secondQBytes_ = 0; 35 | 36 | std::list firstPriorityQ_; 37 | std::list secondPriorityQ_; 38 | }; 39 | 40 | #endif // PACKETS_QUEUE_HPP 41 | -------------------------------------------------------------------------------- /net/include/net/packetvalidator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PACKETVALIDATOR_HPP 2 | #define PACKETVALIDATOR_HPP 3 | 4 | #include 5 | 6 | class Packet; 7 | 8 | namespace cs { 9 | 10 | // validates all network packets 11 | class PacketValidator { 12 | public: 13 | static bool validate(const Packet& packet); 14 | static const cs::PublicKey& getBlockChainKey(); 15 | 16 | private: 17 | static bool validateNetworkPacket(const Packet& packet); 18 | static bool validateNodePacket(const Packet& packet); 19 | }; 20 | } // namespace cs 21 | 22 | #endif // PACKETVALIDATOR_HPP 23 | -------------------------------------------------------------------------------- /net/src/networkcommands.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const char* networkCommandToString(NetworkCommand command) { 4 | switch (command) { 5 | case NetworkCommand::Error: 6 | return "Error"; 7 | case NetworkCommand::VersionRequest: 8 | return "VersionRequest"; 9 | case NetworkCommand::VersionReply: 10 | return "VersionReply"; 11 | case NetworkCommand::Ping: 12 | return "Ping"; 13 | case NetworkCommand::Pong: 14 | return "Pong"; 15 | default: 16 | return "Unknown"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(api-client) 2 | -------------------------------------------------------------------------------- /samples/api-client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 5 | 6 | if (MSVC) 7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /INCREMENTAL:NO /LTCG") 8 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /INCREMENTAL:NO /LTCG") 9 | endif() 10 | 11 | project(api-client) 12 | 13 | add_executable(api-client 14 | api-client.cpp 15 | ) 16 | 17 | target_link_libraries (api-client PUBLIC csconnector lib) 18 | 19 | target_include_directories(api-client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/include) 20 | 21 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17) 22 | set_property(TARGET ${PROJECT_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 23 | set_property(TARGET ${PROJECT_NAME} PROPERTY OUTPUT_NAME api-client) 24 | 25 | configure_msvc_flags() 26 | 27 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 28 | target_link_libraries (client 29 | -static-libstdc++ 30 | ) 31 | endif() 32 | -------------------------------------------------------------------------------- /samples/api-client/api-client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | struct Host 10 | { 11 | std::string ip; 12 | uint16_t port{ 0 }; 13 | }; 14 | 15 | bool test(const Host& host) 16 | { 17 | using namespace apache::thrift; 18 | using namespace apache::thrift::protocol; 19 | using namespace apache::thrift::transport; 20 | 21 | auto ptr = new TSocket(host.ip, host.port); 22 | ptr->setConnTimeout(10000); 23 | stdcxx::shared_ptr socket(ptr); 24 | stdcxx::shared_ptr transport(new TBufferedTransport(socket)); 25 | stdcxx::shared_ptr protocol(new TBinaryProtocol(transport)); 26 | api::APIClient client(protocol); 27 | 28 | bool ret = false; 29 | 30 | try { 31 | std::cout << "connecting to " << host.ip << ':' << host.port << std::endl; 32 | transport->open(); 33 | 34 | std::cout << "make request to node API... "; 35 | api::SyncStateResult result; 36 | client.SyncStateGet(result); 37 | ret = (result.status.code == 0); 38 | std::cout << (ret ? "SUCCESS" : "FAILED") << std::endl; 39 | transport->close(); 40 | } 41 | catch (TException & x) { 42 | std::cout << x.what() << std::endl; 43 | } 44 | return ret; 45 | } 46 | 47 | int main() { 48 | Host host{ "165.22.253.11", 9090 }; 49 | return test(host); 50 | } 51 | -------------------------------------------------------------------------------- /solver/include/solver/result.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cs { 4 | /** 5 | * @enum Result 6 | * 7 | * @brief Values that represent results, special values to return from INodeState methods. Handled by SolverCore. 8 | */ 9 | 10 | enum class Result{ 11 | ///< State completed, SolverCore has to make a transition to another state 12 | Finish, 13 | 14 | ///< SolverCore has to ignore this event, preventing transition to another state 15 | Ignore, 16 | 17 | ///< Critical error in state, SolverCore has to make a transition immediately if it is set, otherwise act as ignore 18 | ///< value 19 | Failure, 20 | 21 | ///< Some errors occur, but there is a possibility to retry another time to do it better 22 | ///< value 23 | Retry, 24 | 25 | ///< State must implement handler for the event but it has not done yet 26 | NotImplemented 27 | }; 28 | } // namespace cs 29 | -------------------------------------------------------------------------------- /solver/include/solver/states/handlebbstate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "defaultstatebehavior.hpp" 3 | 4 | namespace cs { 5 | /** 6 | * @class HandleBBState 7 | * 8 | * @brief A special state to handle a bootstrap. This class cannot be inherited. Acts almost as 9 | * WriteState. Currently is not functional as Node grab the BB handling 10 | * 11 | * @author aae 12 | * @date 02.10.2018 13 | * 14 | * @sa T:WriteState 15 | */ 16 | 17 | class HandleBBState final : public DefaultStateBehavior { 18 | public: 19 | ~HandleBBState() override { 20 | } 21 | 22 | /** 23 | * @fn void final::on(SolverContext& context) override; 24 | * 25 | * @brief Override WriteState behavior. Repeat last block when on and does not require no hashes received when on 26 | * 27 | * @author aae 28 | * @date 02.10.2018 29 | * 30 | * @param [in,out] context The context. 31 | */ 32 | 33 | void on(SolverContext& context) override; 34 | 35 | const char* name() const override { 36 | return "Handle BB"; 37 | } 38 | }; 39 | 40 | } // namespace cs 41 | -------------------------------------------------------------------------------- /solver/include/solver/states/handlertstate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "defaultstatebehavior.hpp" 3 | 4 | namespace cs { 5 | /** 6 | * @class HandleRTState 7 | * 8 | * @brief A special state to handle a new round table. This class cannot be inherited. When on, 9 | * invokes immediately further transition according to round table 10 | * 11 | * @author Alexander Avramenko 12 | * @date 09.10.2018 13 | * 14 | * @sa T:DefaultStateBehavior 15 | * 16 | * ### remarks Aae, 30.09.2018. 17 | */ 18 | 19 | class HandleRTState : public DefaultStateBehavior { 20 | public: 21 | ~HandleRTState() override { 22 | } 23 | 24 | void on(SolverContext& context) override; 25 | 26 | const char* name() const override { 27 | return "Handle RT"; 28 | } 29 | }; 30 | 31 | } // namespace cs 32 | -------------------------------------------------------------------------------- /solver/include/solver/states/normalstate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "defaultstatebehavior.hpp" 7 | 8 | namespace cs { 9 | /** 10 | * @class NormalState 11 | * 12 | * @brief A normal node state. If spammer mode is on in SolverCore, this state implements spam functionality 13 | * 14 | * @author Alexander Avramenko 15 | * @date 09.10.2018 16 | * 17 | * @sa T:DefaultStateBehavior 18 | * 19 | * ### remarks Aae, 30.09.2018. 20 | */ 21 | 22 | class NormalState : public DefaultStateBehavior { 23 | public: 24 | ~NormalState() override { 25 | } 26 | 27 | void on(SolverContext& context) override; 28 | 29 | const char* name() const override { 30 | return "Normal"; 31 | } 32 | }; 33 | 34 | } // namespace cs 35 | -------------------------------------------------------------------------------- /solver/include/solver/states/primitivewritestate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "defaultstatebehavior.hpp" 5 | 6 | namespace cs { 7 | /** 8 | * @class PermanentCollectWriteState 9 | * 10 | * @brief A permanent collect write state. This class cannot be inherited. It is used in special testing mode to serve 11 | * at the same time as Collector (main node) and Writer (write node) during the same round 12 | * 13 | * @author Alexander Avramenko 14 | * @date 11.10.2018 15 | */ 16 | 17 | class PrimitiveWriteState final : public DefaultStateBehavior { 18 | public: 19 | ~PrimitiveWriteState() override { 20 | } 21 | 22 | void on(SolverContext& context) override; 23 | 24 | void off(SolverContext& context) override; 25 | 26 | Result onHash(SolverContext& context, const csdb::PoolHash& pool_hash, const cs::PublicKey& sender) override; 27 | 28 | Result onSyncTransactions(SolverContext& context, cs::RoundNumber round) override; 29 | 30 | const char* name() const override { 31 | return "Primitive Write"; 32 | } 33 | 34 | private: 35 | CallsQueueScheduler::CallTag tag_timeout{CallsQueueScheduler::no_tag}; 36 | 37 | std::vector trusted_candidates; 38 | }; 39 | 40 | } // namespace cs 41 | -------------------------------------------------------------------------------- /solver/include/solver/states/syncstate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "defaultstatebehavior.hpp" 4 | 5 | namespace cs { 6 | /** 7 | * @class SyncState 8 | * 9 | * @brief A synchronize state. Used for node normal mode when some blocks are missed. This 10 | * class cannot be inherited. Currently is not functional as Node grab the block sync 11 | * 12 | * @author Alexander Avramenko 13 | * @date 09.10.2018 14 | * 15 | * @sa T:DefaultStateBehavior 16 | */ 17 | 18 | class SyncState final : public DefaultStateBehavior { 19 | public: 20 | ~SyncState() override { 21 | } 22 | 23 | void on(SolverContext& context) override; 24 | 25 | const char* name() const override { 26 | return "Sync"; 27 | } 28 | }; 29 | 30 | } // namespace cs 31 | -------------------------------------------------------------------------------- /solver/include/solver/states/trustedpoststagestate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "defaultstatebehavior.hpp" 4 | 5 | namespace cs { 6 | /** 7 | * @class TrustedPostStageState 8 | * 9 | * @brief TODO: 10 | * 11 | * @author Alexander Avramenko 12 | * @date 09.10.2018 13 | * 14 | * @sa T:TrustedState 15 | * 16 | * ### remarks Aae, 30.09.2018. 17 | */ 18 | 19 | class TrustedPostStageState final : public DefaultStateBehavior { 20 | public: 21 | ~TrustedPostStageState() override { 22 | } 23 | 24 | void on(SolverContext& context) override; 25 | 26 | void off(SolverContext& context) override; 27 | 28 | Result onStage3(SolverContext& context, const cs::StageThree& stage) override; 29 | 30 | const char* name() const override { 31 | return "Trusted-Z"; 32 | } 33 | void request_stages(SolverContext& context); 34 | void request_stages_neighbors(SolverContext& context); 35 | void mark_outbound_nodes(SolverContext& context); 36 | 37 | protected: 38 | size_t cnt_recv_stages; 39 | 40 | TimeoutTracking timeout_request_stage; 41 | TimeoutTracking timeout_request_neighbors; 42 | TimeoutTracking timeout_force_transition; 43 | }; 44 | 45 | } // namespace cs 46 | -------------------------------------------------------------------------------- /solver/include/solver/states/trustedstage1state.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "defaultstatebehavior.hpp" 5 | //#include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace cs { 13 | class TransactionsPacket; 14 | class IterValidator; 15 | } // namespace cs 16 | 17 | namespace cs { 18 | /** 19 | * @class TrustedStage1State 20 | * 21 | * @brief TODO: 22 | * 23 | * @author Alexander Avramenko 24 | * @date 09.10.2018 25 | * 26 | * @sa T:DefaultStateBehavior 27 | * 28 | * ### remarks Aae, 30.09.2018. 29 | */ 30 | 31 | class TrustedStage1State : public DefaultStateBehavior { 32 | public: 33 | ~TrustedStage1State() override { 34 | } 35 | 36 | void on(SolverContext& context) override; 37 | 38 | void off(SolverContext& context) override; 39 | 40 | Result onSyncTransactions(SolverContext& context, cs::RoundNumber round) override; 41 | 42 | Result onHash(SolverContext& context, const csdb::PoolHash& pool_hash, const cs::PublicKey& sender) override; 43 | 44 | const char* name() const override { 45 | return "Trusted-1"; 46 | } 47 | 48 | protected: 49 | bool enough_hashes{false}; 50 | bool transactions_checked{false}; 51 | bool min_time_expired{false}; 52 | void finalizeStage(SolverContext& context); 53 | 54 | // TimeoutTracking min_time_tracking; 55 | cs::StageOne stage; 56 | size_t likeMineHashes; 57 | size_t differentHashes; 58 | cs::ConfidantsKeys differKeys; 59 | 60 | cs::Hash build_vector(SolverContext& context, TransactionsPacket& trans_pack, cs::PacketsVector& smartsPackets); 61 | cs::Hash formHashFromCharacteristic(const cs::Characteristic& characteristic); 62 | 63 | std::unique_ptr pValidator_; 64 | }; 65 | 66 | } // namespace cs 67 | -------------------------------------------------------------------------------- /solver/include/solver/states/trustedstage2state.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "defaultstatebehavior.hpp" 5 | 6 | namespace cs { 7 | /** 8 | * @class TrustedStage2State 9 | * 10 | * @brief TODO: 11 | * 12 | * @author Alexander Avramenko 13 | * @date 09.10.2018 14 | * 15 | * @sa T:TrustedState 16 | * 17 | * ### remarks Aae, 30.09.2018. 18 | */ 19 | 20 | class TrustedStage2State final : public DefaultStateBehavior { 21 | public: 22 | ~TrustedStage2State() override { 23 | } 24 | 25 | /** 26 | * @fn virtual void final::on(SolverContext& context) override; 27 | * 28 | * @brief Sends stage-1 result 29 | * 30 | * @author Alexander Avramenko 31 | * @date 26.10.2018 32 | * 33 | * @param [in,out] context The context. 34 | */ 35 | 36 | void on(SolverContext& context) override; 37 | 38 | void off(SolverContext& context) override; 39 | 40 | Result onStage1(SolverContext& context, const cs::StageOne& stage) override; 41 | 42 | const char* name() const override { 43 | return "Trusted-2"; 44 | } 45 | 46 | private: 47 | cs::StageTwo stage; 48 | 49 | size_t cnt_recv_stages; 50 | 51 | // timeout tracking 52 | 53 | TimeoutTracking timeout_request_stage; 54 | TimeoutTracking timeout_request_neighbors; 55 | TimeoutTracking timeout_force_transition; 56 | 57 | // requests stages from corresponded nodes 58 | void request_stages(SolverContext& context); 59 | 60 | // requests stages from any available neighbor nodes 61 | void request_stages_neighbors(SolverContext& context); 62 | 63 | // forces transition to next stage 64 | void mark_outbound_nodes(SolverContext& context); 65 | }; 66 | 67 | } // namespace cs 68 | -------------------------------------------------------------------------------- /solver/include/solver/states/trustedstage3state.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "defaultstatebehavior.hpp" 5 | 6 | #include 7 | 8 | namespace cs { 9 | /** 10 | * @class TrustedStage3State 11 | * 12 | * @brief TODO: 13 | * 14 | * @author Alexander Avramenko 15 | * @date 09.10.2018 16 | * 17 | * @sa T:TrustedState 18 | * 19 | * ### remarks Aae, 30.09.2018. 20 | */ 21 | 22 | struct StakeHolder { 23 | StakeHolder(PublicKey pKey, csdb::Amount st) { 24 | key = pKey; 25 | stake = st; 26 | } 27 | PublicKey key; 28 | csdb::Amount stake; 29 | }; 30 | 31 | class TrustedStage3State final : public DefaultStateBehavior { 32 | public: 33 | ~TrustedStage3State() override { 34 | } 35 | 36 | virtual void on(SolverContext& context) override; 37 | 38 | void off(SolverContext& context) override; 39 | 40 | virtual Result onStage2(SolverContext& context, const cs::StageTwo& stage) override; 41 | 42 | const char* name() const override { 43 | return "Trusted-3"; 44 | } 45 | 46 | 47 | protected: 48 | // timeout tracking 49 | 50 | TimeoutTracking timeout_request_stage; 51 | TimeoutTracking timeout_request_neighbors; 52 | TimeoutTracking timeout_force_transition; 53 | 54 | size_t cnt_recv_stages; 55 | cs::StageThree stage; 56 | std::vector next_round_trust; 57 | std::vector next_round_hashes; 58 | 59 | void trusted_election(SolverContext& context); 60 | bool pool_solution_analysis(SolverContext& context); 61 | bool take_urgent_decision(SolverContext& context); 62 | Result finalizeStageThree(SolverContext& context); 63 | 64 | void request_stages(SolverContext& context); 65 | void request_stages_neighbors(SolverContext& context); 66 | // forces transition to next stage 67 | void mark_outbound_nodes(SolverContext& context, cs::RoundNumber round); 68 | }; 69 | 70 | } // namespace cs 71 | -------------------------------------------------------------------------------- /solver/include/solver/states/waitingstate.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WAITING_STAGE_HPP 2 | #define WAITING_STAGE_HPP 3 | 4 | #include 5 | #include 6 | #include "defaultstatebehavior.hpp" 7 | 8 | namespace cs { 9 | /** 10 | * @class WaitingState 11 | * 12 | * @brief A waiting state. This class cannot be inherited. Waits for round info until timeout expired. On timeout 13 | * starts conversation with WritingState node and "next" WaitingState node to provide new round start 14 | * 15 | * @author Alexander Avramenko 16 | * @date 02.11.2018 17 | */ 18 | 19 | class WaitingState final : public DefaultStateBehavior { 20 | public: 21 | ~WaitingState() override { 22 | } 23 | 24 | void on(SolverContext& context) override; 25 | 26 | void off(SolverContext& context) override; 27 | 28 | const char* name() const override { 29 | return myName_.c_str(); 30 | } 31 | 32 | private: 33 | constexpr static const char* prefix_ = "Waiting"; 34 | const static uint32_t sendRoundTableDelayMs_ = 6000; 35 | 36 | uint8_t writingQueueNumber_ = {0}; 37 | std::string myName_ = {prefix_}; 38 | 39 | TimeoutTracking roundTimeout_; 40 | 41 | void activate_new_round(SolverContext& context); 42 | }; 43 | } // namespace cs 44 | 45 | #endif // WAITING_STAGE_HPP 46 | -------------------------------------------------------------------------------- /solver/include/solver/states/writingstate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "defaultstatebehavior.hpp" 4 | 5 | namespace cs { 6 | /** 7 | * @class WritingState 8 | * 9 | * @brief A writing state. This class cannot be inherited. Writes new block and send round info to other nodes 10 | * 11 | * @author Alexander Avramenko 12 | * @date 02.11.2018 13 | */ 14 | 15 | class WritingState final : public DefaultStateBehavior { 16 | public: 17 | ~WritingState() override { 18 | } 19 | 20 | void on(SolverContext& context) override; 21 | 22 | const char* name() const override { 23 | return "Writing"; 24 | } 25 | }; 26 | } // namespace cs 27 | -------------------------------------------------------------------------------- /solver/include/solver/timeouttracking.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cs { 6 | 7 | class TimeoutTracking { 8 | public: 9 | void start(CallsQueueScheduler& scheduler, uint32_t wait_for_ms, const CallsQueueScheduler::ProcType& proc, bool replace_existing, 10 | CallsQueueScheduler::CallTag tag = CallsQueueScheduler::auto_tag); 11 | 12 | bool cancel(); 13 | 14 | bool is_active() const { 15 | return call_tag != CallsQueueScheduler::no_tag; 16 | } 17 | 18 | private: 19 | CallsQueueScheduler* pscheduler{nullptr}; 20 | CallsQueueScheduler::CallTag call_tag{CallsQueueScheduler::no_tag}; 21 | }; 22 | 23 | } // namespace cs 24 | -------------------------------------------------------------------------------- /solver/src/states/handlebbstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace cs { 6 | 7 | void HandleBBState::on(SolverContext& context) { 8 | cswarning() << name() << ": Bootstrap processing is implemented in Node class"; 9 | DefaultStateBehavior::on(context); 10 | } 11 | 12 | } // namespace cs 13 | -------------------------------------------------------------------------------- /solver/src/states/handlertstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace cs { 7 | void HandleRTState::on(SolverContext& context) { 8 | auto role = context.role(); 9 | switch (role) { 10 | case Role::Trusted: 11 | context.request_role(Role::Trusted); 12 | break; 13 | case Role::Normal: 14 | context.request_role(Role::Normal); 15 | break; 16 | default: 17 | cserror() << name() << ": unknown role requested"; 18 | break; 19 | } 20 | } 21 | 22 | } // namespace cs 23 | -------------------------------------------------------------------------------- /solver/src/states/normalstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma warning(push) 6 | //#pragma warning(disable: 4267 4244 4100 4245) 7 | #include 8 | #pragma warning(pop) 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace cs { 17 | 18 | void NormalState::on(SolverContext& context) { 19 | DefaultStateBehavior::on(context); 20 | } 21 | 22 | } // namespace cs 23 | -------------------------------------------------------------------------------- /solver/src/states/syncstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace cs { 5 | 6 | void SyncState::on(SolverContext& context) { 7 | DefaultStateBehavior::on(context); 8 | } 9 | 10 | } // namespace cs 11 | -------------------------------------------------------------------------------- /solver/src/states/writingstate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace cs { 6 | 7 | void WritingState::on(SolverContext& context) { 8 | // simply try to spawn next round 9 | csdebug() << name() << ": spawn next round"; 10 | context.sendRoundTable(); 11 | } 12 | 13 | } // namespace cs 14 | -------------------------------------------------------------------------------- /solver/src/timeouttracking.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace cs { 4 | 5 | void TimeoutTracking::start(CallsQueueScheduler& scheduler, uint32_t wait_for_ms, const CallsQueueScheduler::ProcType& proc, bool replace_existing, 6 | CallsQueueScheduler::CallTag tag) { 7 | pscheduler = &scheduler; 8 | call_tag = pscheduler->InsertOnce(wait_for_ms, 9 | [this, proc]() { 10 | // extra test whether to execute proc(): 11 | if (call_tag != CallsQueueScheduler::no_tag) { 12 | call_tag = CallsQueueScheduler::no_tag; 13 | proc(); 14 | } 15 | }, 16 | replace_existing, tag); 17 | } 18 | 19 | bool TimeoutTracking::cancel() { 20 | if (call_tag != CallsQueueScheduler::no_tag) { 21 | pscheduler->Remove(call_tag); 22 | call_tag = CallsQueueScheduler::no_tag; 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | } // namespace cs 29 | -------------------------------------------------------------------------------- /solver/tests/mock/Solver/solver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | constexpr const size_t MAX_CONF_NUMBER = 5; 6 | 7 | class Node; 8 | namespace csdb 9 | { 10 | class Pool; 11 | } 12 | 13 | namespace cs 14 | { 15 | class Fee 16 | { 17 | public: 18 | 19 | MOCK_METHOD2(CountFeesInPool, void(const Node*, const csdb::Pool*)); 20 | }; 21 | 22 | class Solver 23 | { 24 | public: 25 | }; 26 | } -------------------------------------------------------------------------------- /solver/tests/mock/Solver/transactionsvalidator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace cs 7 | { 8 | 9 | class TransactionsValidator 10 | { 11 | public: 12 | 13 | struct Config 14 | {}; 15 | 16 | TransactionsValidator(const cs::WalletsState&, const Config&) 17 | {} 18 | 19 | MOCK_METHOD1(reset, void(size_t)); 20 | MOCK_METHOD3(validateTransaction, bool(csdb::Transaction, size_t, uint8_t&)); 21 | MOCK_METHOD3(validateByGraph, void(cs::Bytes&, const std::vector&, const csdb::Pool&)); 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /solver/tests/mock/Solver/walletsstate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace cs 5 | { 6 | class WalletsState 7 | { 8 | public: 9 | 10 | MOCK_METHOD0(updateFromSource, void()); 11 | }; 12 | } -------------------------------------------------------------------------------- /solver/tests/mock/blake2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | inline void blake2s(const uint8_t*, size_t, const uint8_t*, size_t, void*, size_t) 4 | { 5 | } -------------------------------------------------------------------------------- /solver/tests/mock/callsqueuescheduler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace slv2 4 | { 5 | class CallsQueueScheduler 6 | { 7 | public: 8 | using ProcType = std::function; 9 | using CallTag = uintptr_t; 10 | 11 | CallsQueueScheduler() = default; 12 | 13 | CallsQueueScheduler(const CallsQueueScheduler&) 14 | {} 15 | 16 | constexpr static CallTag no_tag = 0; 17 | 18 | }; 19 | } -------------------------------------------------------------------------------- /solver/tests/mock/csdb/pool.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace csdb 9 | { 10 | class PoolHash 11 | { 12 | public: 13 | 14 | PoolHash() = default; 15 | PoolHash(const PoolHash&) 16 | {} 17 | 18 | MOCK_METHOD0(to_binary, cs::Bytes&()); 19 | }; 20 | 21 | class Address 22 | { 23 | public: 24 | using WalletId = uint32_t; 25 | 26 | Address() = default; 27 | Address(const Address&) 28 | {} 29 | 30 | MOCK_CONST_METHOD0(is_wallet_id, bool()); 31 | MOCK_CONST_METHOD0(wallet_id, WalletId()); 32 | MOCK_CONST_METHOD0(public_key, const cs::Bytes&()); 33 | }; 34 | 35 | class Amount 36 | { 37 | public: 38 | Amount() = default; 39 | Amount(const Amount&) 40 | {} 41 | 42 | MOCK_CONST_METHOD0(to_double, double()); 43 | }; 44 | 45 | class Transaction 46 | { 47 | public: 48 | Transaction() = default; 49 | Transaction(const Transaction&) 50 | {} 51 | 52 | MOCK_CONST_METHOD0(innerID, int64_t()); 53 | MOCK_CONST_METHOD0(source, Address()); 54 | MOCK_CONST_METHOD0(target, Address()); 55 | MOCK_CONST_METHOD0(amount, Amount()); 56 | MOCK_CONST_METHOD1(verify_signature, bool(cs::Bytes)); 57 | }; 58 | 59 | class Pool 60 | { 61 | public: 62 | Pool() = default; 63 | 64 | Pool(const Pool&) 65 | {} 66 | 67 | Pool& operator=(const Pool&) 68 | { 69 | return *this; 70 | } 71 | 72 | MOCK_CONST_METHOD0(sequence, size_t()); 73 | MOCK_METHOD1(set_sequence, void(size_t)); 74 | MOCK_CONST_METHOD0(transactions_count, size_t()); 75 | MOCK_CONST_METHOD0(transactions, const std::vector()); 76 | MOCK_METHOD0(verify_signature, bool()); 77 | MOCK_METHOD1(add_transaction, void(const Transaction)); 78 | MOCK_CONST_METHOD0(writer_public_key, cs::Bytes()); 79 | }; 80 | 81 | } 82 | -------------------------------------------------------------------------------- /solver/tests/mock/csnode/blockchain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class BlockChain 7 | { 8 | public: 9 | using WalletData = cs::WalletsCache::WalletData; 10 | 11 | BlockChain() 12 | {} 13 | 14 | BlockChain(const BlockChain &) 15 | {} 16 | 17 | MOCK_METHOD0(getLastHash, csdb::PoolHash&()); 18 | MOCK_METHOD1(getHashBySequence, csdb::PoolHash&(uint32_t)); 19 | MOCK_METHOD0(getLastSequence, size_t()); 20 | MOCK_CONST_METHOD2(findWalletData, void(const csdb::Address::WalletId, WalletData&)); 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /solver/tests/mock/csnode/conveyer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cs 7 | { 8 | class TransactionsPacket 9 | { 10 | public: 11 | MOCK_CONST_METHOD0(transactions, std::vector()); 12 | MOCK_METHOD1(addTransaction, bool(const csdb::Transaction&)); 13 | MOCK_CONST_METHOD0(transactionsCount, size_t()); 14 | }; 15 | 16 | class Characteristic 17 | { 18 | public: 19 | cs::Bytes mask; 20 | }; 21 | 22 | struct RoundTable 23 | { 24 | size_t round = 0; 25 | PublicKey general; 26 | std::vector confidants; 27 | std::vector hashes; 28 | }; 29 | 30 | class Conveyer 31 | { 32 | public: 33 | 34 | static Conveyer& instance() 35 | { 36 | static Conveyer impl; 37 | return impl; 38 | } 39 | 40 | MOCK_CONST_METHOD0(roundTable, RoundTable&()); 41 | MOCK_CONST_METHOD0(transactionsPacketTable, std::set&()); 42 | MOCK_CONST_METHOD1(packet, TransactionsPacket&(Hash)); 43 | MOCK_CONST_METHOD1(setCharacteristic, void(const cs::Characteristic&)); 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /solver/tests/mock/csnode/csnode.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Node 4 | { 5 | public: 6 | }; 7 | -------------------------------------------------------------------------------- /solver/tests/mock/csnode/transactionspacket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once -------------------------------------------------------------------------------- /solver/tests/mock/csnode/walletscache.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace cs 6 | { 7 | class WalletsCache 8 | { 9 | public: 10 | 11 | struct WalletData 12 | { 13 | using Address = std::array; 14 | Address address_; 15 | }; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /solver/tests/mock/sodium.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | inline void crypto_sign_detached(const uint8_t*, unsigned long long*, const uint8_t*, size_t, const uint8_t*) 4 | { 5 | } 6 | 7 | inline int crypto_sign_verify_detached(const uint8_t*, const uint8_t*, size_t, const uint8_t*) 8 | { 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /solver/tests/mock/timeouttracking.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace slv2 7 | { 8 | class TimeoutTracking 9 | { 10 | public: 11 | 12 | TimeoutTracking() = default; 13 | 14 | TimeoutTracking(const TimeoutTracking&) 15 | {} 16 | 17 | MOCK_METHOD4(start, void(CallsQueueScheduler&, size_t, CallsQueueScheduler::ProcType, bool)); 18 | MOCK_METHOD0(cancel, bool()); 19 | }; 20 | } -------------------------------------------------------------------------------- /solver/tests/test_trustedstage2state.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | TEST(TrustedStage2State, TrivialMethods) 7 | { 8 | using namespace ::testing; 9 | 10 | NiceMock mock; 11 | 12 | using namespace slv2; 13 | TrustedStage2State state; 14 | 15 | EXPECT_EQ(Result::Ignore, state.onBlock(mock.context, mock.block, mock.sender1)); 16 | EXPECT_EQ(Result::Ignore, state.onTransactionList(mock.context, mock.tl)); 17 | EXPECT_EQ(Result::Ignore, state.onHash(mock.context, mock.hash, mock.sender1)); 18 | EXPECT_EQ(Result::Ignore, state.onStage2(mock.context, mock.stage2)); 19 | EXPECT_EQ(Result::Ignore, state.onStage3(mock.context, mock.stage3)); 20 | EXPECT_EQ(Result::Ignore, state.onTransaction(mock.context, mock.trans)); 21 | EXPECT_EQ(Result::Finish, state.onRoundTable(mock.context, 1)); 22 | } 23 | 24 | TEST(TrustedStage2State, TrList_then_all_hashes) 25 | { 26 | using namespace ::testing; 27 | 28 | NiceMock mock; 29 | 30 | using namespace ::testing; 31 | using namespace slv2; 32 | 33 | TrustedStage2State state; 34 | 35 | EXPECT_NO_THROW(state.on(mock.context)); 36 | 37 | // context.enough_stage1() => Ignore || Finish 38 | struct SequenceBool 39 | { 40 | SequenceBool(bool start_from) 41 | : flag(!start_from) 42 | {} 43 | bool flag; 44 | bool Next() 45 | { 46 | flag = !flag; 47 | return flag; 48 | } 49 | }; 50 | SequenceBool seq(false); 51 | EXPECT_CALL(mock.context, enough_stage1) 52 | .Times(2) // on(), onHash()-#3 53 | .WillRepeatedly(Invoke(&seq, &SequenceBool::Next)); 54 | 55 | EXPECT_EQ(Result::Ignore, state.onStage1(mock.context, mock.stage1)); 56 | EXPECT_EQ(Result::Finish, state.onStage1(mock.context, mock.stage1)); 57 | } 58 | -------------------------------------------------------------------------------- /solver/tests/tests_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char** argv) 8 | { 9 | #if defined(__MINGW32__) 10 | std::setlocale(LC_ALL, "Russian"); 11 | #elif defined(_WIN32) 12 | std::setlocale(LC_ALL, "ru-RU"); 13 | #else 14 | std::setlocale(LC_ALL, "ru_RU.UTF-8"); 15 | #endif 16 | 17 | ::testing::InitGoogleTest(&argc, argv); 18 | ::testing::InitGoogleMock(&argc, argv); 19 | 20 | return RUN_ALL_TESTS(); 21 | } 22 | 23 | TEST(Init, Done) 24 | { 25 | EXPECT_FALSE(false); 26 | EXPECT_TRUE(true); 27 | } 28 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | find_package(Threads REQUIRED) 4 | 5 | add_subdirectory(lib_system) 6 | add_subdirectory(csnode) 7 | add_subdirectory(lmdbxx) 8 | add_subdirectory(testprogram) 9 | -------------------------------------------------------------------------------- /tests/csnode/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TEST_NAME nodetests) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 5 | 6 | file(GLOB SRCS *.cpp) 7 | list(APPEND SRCS 8 | "${CMAKE_CURRENT_SOURCE_DIR}/../../client/config/config.cpp" 9 | ) 10 | 11 | add_executable(${TEST_NAME} ${SRCS}) 12 | 13 | target_include_directories(${TEST_NAME} PUBLIC 14 | ${CMAKE_CURRENT_SOURCE_DIR}/../../client/include/client 15 | ) 16 | 17 | suppress_boost_cmake_warnings() 18 | 19 | set(Boost_USE_STATIC_LIBS ON) 20 | if(NOT APPLE) 21 | set(Boost_USE_STATIC_RUNTIME ON) 22 | endif() 23 | 24 | find_package(Boost REQUIRED COMPONENTS program_options) 25 | 26 | if(NOT MSVC AND NOT APPLE) 27 | # some way to resolve cyclic dependencies 28 | set(LINKER_START_GROUP "-Wl,--start-group") 29 | set(LINKER_END_GROUP "-Wl,--end-group") 30 | endif() 31 | 32 | target_link_libraries(${TEST_NAME} ${LINKER_START_GROUP} csdb csconnector solver csnode net gtest gmock ${LINKER_END_GROUP} 33 | Boost::program_options 34 | ) 35 | 36 | add_test(NAME ${TEST_NAME} 37 | COMMAND ${TEST_NAME}) 38 | 39 | configure_msvc_flags() 40 | -------------------------------------------------------------------------------- /tests/csnode/amount_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include 4 | #include "clientconfigmock.hpp" 5 | #include "gtest/gtest.h" 6 | #include 7 | #include 8 | 9 | constexpr std::array, 14> feeLevels = { 10 | std::make_tuple(5 * 1024, 0.087402, 0.008740), // this is min fee value 11 | std::make_tuple(20 * 1024, 0.174805, 0.034961), 12 | std::make_tuple(50 * 1024, 0.437500, 0.139648), 13 | std::make_tuple(100 * 1024, 17.87109, 17.87109), 14 | std::make_tuple(256 * 1024, 89.55078, 89.55078), 15 | std::make_tuple(512 * 1024, 358.39844, 358.39844), 16 | std::make_tuple(768 * 1024, 1435.5469, 1435.5469), 17 | std::make_tuple(1024 * 1024, 5732.4219, 5732.4219), 18 | std::make_tuple(5 * 1024 * 1024, 22949.21875, 22949.21875), 19 | std::make_tuple(15 * 1024 * 1024, 91699.21875, 91699.21875), 20 | std::make_tuple(50 * 1024 * 1024, 367187.5, 367187.5), 21 | std::make_tuple(100 * 1024 * 1024, 1464843.75, 1464843.75), 22 | std::make_tuple(500 * 1024 * 1024, 5869140.625, 5869140.625), 23 | std::make_tuple(1000 * 1024 * 1024, 23437500.0, 23437500.0) 24 | }; 25 | 26 | TEST(Amount, to_double) { 27 | csdb::Amount val{0, 18000000000000000}; 28 | ASSERT_EQ(val.to_double(), 0.018); 29 | 30 | std::cout << "transfer / call" << std::endl; 31 | for (int i = 0; i < 14; ++i) { 32 | std::cout << i + 1 << " <" << std::get<0>(feeLevels[i]) << '\t'; 33 | csdb::AmountCommission comm(std::get<2>(feeLevels[i])); 34 | std::cout << comm.get_raw() << '\t' << comm.to_double() << '\t'; 35 | csdb::Amount amount(comm.to_double()); 36 | std::cout << amount.to_string() << " (" << amount.integral() << '.' << std::setfill('0') << std::setw(18) << amount.fraction() << ')'; 37 | std::cout << std::endl; 38 | } 39 | 40 | std::cout << "deployment" << std::endl; 41 | for (int i = 0; i < 14; ++i) { 42 | std::cout << i + 1 << " <" << std::get<0>(feeLevels[i]) << '\t'; 43 | csdb::AmountCommission comm(std::get<1>(feeLevels[i])); 44 | std::cout << comm.get_raw() << '\t' << comm.to_double() << '\t'; 45 | csdb::Amount amount(comm.to_double()); 46 | std::cout << amount.to_string() << " (" << amount.integral() << '.' << std::setfill('0') << std::setw(18) << amount.fraction() << ')'; 47 | std::cout << std::endl; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/csnode/bitheap_tests.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include 3 | 4 | TEST(BeatHeap, BasicOperations) { 5 | 6 | using TransactionId = int64_t; 7 | static constexpr size_t BitSize = 1024; 8 | using Heap = cs::BitHeap; 9 | Heap heap; 10 | 11 | ASSERT_FALSE(heap.contains(37)); 12 | ASSERT_EQ(heap.count(), 0); 13 | ASSERT_TRUE(heap.empty()); 14 | 15 | heap.push(37); 16 | 17 | ASSERT_TRUE(heap.contains(37)); 18 | ASSERT_NE(heap.count(), 0); 19 | ASSERT_FALSE(heap.empty()); 20 | ASSERT_FALSE(heap.contains(2)); 21 | 22 | heap.pop(37); 23 | 24 | ASSERT_FALSE(heap.contains(37)); 25 | 26 | ASSERT_EQ(heap.count(), 0); 27 | ASSERT_TRUE(heap.empty()); 28 | 29 | heap.push(137); 30 | heap.push(1037); 31 | 32 | ASSERT_FALSE(heap.contains(37)); 33 | ASSERT_TRUE(heap.contains(137)); 34 | ASSERT_TRUE(heap.contains(1037)); 35 | ASSERT_EQ(heap.count(), 2); 36 | ASSERT_FALSE(heap.empty()); 37 | 38 | heap.pop(1037); 39 | 40 | ASSERT_FALSE(heap.contains(37)); 41 | ASSERT_TRUE(heap.contains(137)); 42 | ASSERT_FALSE(heap.contains(1037)); 43 | ASSERT_TRUE(heap.getGreatest() == 137); 44 | ASSERT_EQ(heap.count(), 1); 45 | ASSERT_FALSE(heap.empty()); 46 | 47 | heap.push(1000); 48 | heap.push(1001); 49 | heap.push(1002); 50 | heap.push(1004); 51 | heap.push(1005); 52 | ASSERT_TRUE(heap.getGreatest() == 1005); 53 | heap.pop(1004); 54 | heap.pop(1005); 55 | ASSERT_TRUE(heap.getGreatest() == 1002); 56 | ASSERT_FALSE(heap.contains(2)); 57 | ASSERT_EQ(heap.count(), 4); 58 | 59 | } 60 | -------------------------------------------------------------------------------- /tests/csnode/blockchain_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include "clientconfigmock.hpp" 4 | #include "gtest/gtest.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | TEST(BlockChain, block_service_info) { 11 | csdb::Pool block{}; 12 | 13 | ASSERT_FALSE(BlockChain::isBootstrap(block)); 14 | BlockChain::setBootstrap(block, false); 15 | ASSERT_FALSE(BlockChain::isBootstrap(block)); 16 | BlockChain::setBootstrap(block, true); 17 | ASSERT_TRUE(BlockChain::isBootstrap(block)); 18 | BlockChain::setBootstrap(block, false); 19 | ASSERT_FALSE(BlockChain::isBootstrap(block)); 20 | 21 | block = csdb::Pool{}; 22 | 23 | ASSERT_FALSE(BlockChain::isBootstrap(block)); 24 | BlockChain::setBootstrap(block, true); 25 | ASSERT_TRUE(BlockChain::isBootstrap(block)); 26 | BlockChain::setBootstrap(block, true); 27 | ASSERT_TRUE(BlockChain::isBootstrap(block)); 28 | BlockChain::setBootstrap(block, false); 29 | ASSERT_FALSE(BlockChain::isBootstrap(block)); 30 | } -------------------------------------------------------------------------------- /tests/csnode/clientconfigmock.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by User on 01.10.2018. 3 | // 4 | 5 | #ifndef PROJECT_MOCKCLIENTCONFIG_HPP 6 | #define PROJECT_MOCKCLIENTCONFIG_HPP 7 | 8 | #include 9 | #include 10 | #include 11 | #include "config.hpp" 12 | 13 | class MockConfig : public Config { 14 | public: 15 | MOCK_CONST_METHOD0(getInputEndpoint, const EndpointData&()); 16 | MOCK_CONST_METHOD0(getOutputEndpoint, const EndpointData&()); 17 | 18 | MOCK_CONST_METHOD0(getSignalServerEndpoint, const EndpointData&()); 19 | 20 | MOCK_CONST_METHOD0(getBootstrapType, BootstrapType()); 21 | MOCK_CONST_METHOD0(getIpList, const std::vector&()); 22 | 23 | MOCK_CONST_METHOD0(getMyPublicKey, const cs::PublicKey&()); 24 | MOCK_CONST_METHOD0(getPathToDB, const std::string&()); 25 | 26 | MOCK_METHOD0(isGood, bool()); 27 | 28 | MOCK_CONST_METHOD0(useIPv6, bool()); 29 | MOCK_CONST_METHOD0(hasTwoSockets, bool()); 30 | 31 | MOCK_CONST_METHOD0(isSymmetric, bool()); 32 | MOCK_CONST_METHOD0(getAddressEndpoint, const EndpointData&()); 33 | }; 34 | 35 | #endif // PROJECT_MOCKCLIENTCONFIG_HPP 36 | -------------------------------------------------------------------------------- /tests/csnode/dynamicbuffer_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | using namespace cs; 10 | 11 | TEST(DynamicBuffer, equal_by_size) { 12 | DynamicBuffer a; 13 | DynamicBuffer b(a); 14 | 15 | ASSERT_TRUE(a == b); 16 | } 17 | 18 | TEST(DynamicBuffer, get_element_by_index) { 19 | char str[] = "teststring"; 20 | size_t size = strlen(str) + 1; 21 | DynamicBuffer a(size); 22 | auto buffer = a.get(); 23 | std::copy(std::begin(str), std::end(str), buffer); 24 | 25 | ASSERT_TRUE(a[3] == str[3]); 26 | } 27 | 28 | TEST(DynamicBuffer, stl_interface) { 29 | char str[] = "cba"; 30 | size_t size = strlen(str) + 1; 31 | DynamicBuffer a(size); 32 | auto buffer = a.get(); 33 | std::copy(std::begin(str), std::end(str), buffer); 34 | std::sort(a.begin(), a.end() - 1); 35 | 36 | ASSERT_STREQ("abc", *a); 37 | } 38 | -------------------------------------------------------------------------------- /tests/csnode/main.cpp: -------------------------------------------------------------------------------- 1 | #include "gmock/gmock.h" 2 | #include "gtest/gtest.h" 3 | 4 | int main(int argc, char **argv) { 5 | ::testing::InitGoogleMock(&argc, argv); 6 | int ret = RUN_ALL_TESTS(); 7 | return ret; 8 | } 9 | -------------------------------------------------------------------------------- /tests/csnode/node_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include "clientconfigmock.hpp" 12 | #include "gtest/gtest.h" 13 | #include "solvermock.hpp" 14 | #include "transportmock.hpp" 15 | 16 | TEST(NodeTest, connection) { 17 | MockConfig config; 18 | 19 | ASSERT_EQ(true, true); 20 | } 21 | -------------------------------------------------------------------------------- /tests/csnode/packetqueue_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const size_t kMaxPacketTransactions = 100; 5 | const size_t kMaxPacketsPerRound = 10; 6 | const size_t kMaxQueueSize = 100; 7 | 8 | class PacketCreator { 9 | public: 10 | using Pointer = void*; 11 | using Default = int; 12 | 13 | template 14 | constexpr static auto create() { 15 | if constexpr (std::is_pointer_v) { 16 | return new cs::PacketQueue(kMaxQueueSize, kMaxPacketTransactions, kMaxPacketsPerRound); 17 | } 18 | else { 19 | return cs::PacketQueue(kMaxQueueSize, kMaxPacketTransactions, kMaxPacketsPerRound); 20 | } 21 | } 22 | }; 23 | 24 | TEST(PacketQueue, CreationAndDestroy) { 25 | cs::PacketQueue* queue = PacketCreator::create(); 26 | delete queue; 27 | 28 | queue = nullptr; 29 | 30 | ASSERT_EQ(queue, nullptr); 31 | } 32 | 33 | TEST(PacketQueue, EmptyState) { 34 | cs::PacketQueue queue = PacketCreator::create(); 35 | ASSERT_EQ(queue.isEmpty(), true); 36 | } 37 | 38 | void addTransactions(cs::PacketQueue& queue) { 39 | for (size_t i = 0; i < (kMaxPacketTransactions * 2) + 1; ++i) { 40 | queue.push(csdb::Transaction{}); 41 | } 42 | } 43 | 44 | TEST(PacketQueue, pushTransaction) { 45 | cs::PacketQueue queue = PacketCreator::create(); 46 | addTransactions(queue); 47 | 48 | ASSERT_EQ(queue.size(), 3); 49 | } 50 | 51 | TEST(PacketQueue, popTransactionsBlocks) { 52 | cs::PacketQueue queue = PacketCreator::create(); 53 | addTransactions(queue); 54 | 55 | while (!queue.isEmpty()) { 56 | queue.pop(); 57 | } 58 | 59 | ASSERT_EQ(queue.isEmpty(), true); 60 | } 61 | -------------------------------------------------------------------------------- /tests/csnode/pool_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include "gtest/gtest.h" 4 | -------------------------------------------------------------------------------- /tests/csnode/smartcontractref_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include 4 | #include "clientconfigmock.hpp" 5 | #include "gtest/gtest.h" 6 | #include "nodemock.hpp" 7 | #include "solvermock.hpp" 8 | #include "transportmock.hpp" 9 | 10 | TEST(SmartContractRef, constructors) { 11 | cs::SmartContractRef r1; 12 | ASSERT_FALSE(r1.is_valid()); 13 | 14 | r1.sequence = 0; 15 | r1.transaction = 0; 16 | ASSERT_TRUE(r1.is_valid()); 17 | 18 | cs::SmartContractRef r2(0, 1); 19 | ASSERT_TRUE(r2.is_valid()); 20 | } 21 | 22 | TEST(SmartContractRef, comparisons) { 23 | cs::SmartContractRef ref_1_0(1, 0); 24 | cs::SmartContractRef ref_1_1(1, 1); 25 | cs::SmartContractRef ref_2_0(2, 0); 26 | cs::SmartContractRef ref_2_1(2, 1); 27 | cs::SmartContractRef ref_invalid; 28 | 29 | ASSERT_GT(ref_1_1, ref_1_0); 30 | ASSERT_LT(ref_1_0, ref_1_1); 31 | 32 | ASSERT_GT(ref_2_0, ref_1_0); 33 | ASSERT_GT(ref_2_0, ref_1_1); 34 | ASSERT_LT(ref_1_0, ref_2_0); 35 | ASSERT_LT(ref_1_1, ref_2_0); 36 | 37 | ASSERT_GT(ref_2_1, ref_1_0); 38 | ASSERT_GT(ref_2_1, ref_1_1); 39 | ASSERT_GT(ref_2_1, ref_2_0); 40 | ASSERT_LT(ref_1_0, ref_2_1); 41 | ASSERT_LT(ref_1_1, ref_2_1); 42 | ASSERT_LT(ref_2_0, ref_2_1); 43 | 44 | ASSERT_LT(ref_invalid, ref_1_0); 45 | ASSERT_FALSE(ref_invalid < ref_invalid); 46 | ASSERT_FALSE(ref_1_0 < ref_invalid); 47 | ASSERT_TRUE(ref_1_0 > ref_invalid); 48 | 49 | ASSERT_GT(ref_1_0, ref_invalid); 50 | ASSERT_FALSE(ref_invalid > ref_1_0); 51 | ASSERT_TRUE(ref_1_0 > ref_invalid); 52 | ASSERT_FALSE(ref_invalid > ref_invalid); 53 | 54 | ASSERT_EQ(ref_1_0, ref_1_0); 55 | ASSERT_EQ(ref_invalid, ref_invalid); 56 | ASSERT_FALSE(ref_1_0 == ref_1_1); 57 | ASSERT_FALSE(ref_1_0 == ref_2_0); 58 | ASSERT_FALSE(ref_invalid == ref_1_0); 59 | ASSERT_FALSE(ref_2_0 == ref_1_0); 60 | ASSERT_FALSE(ref_2_0 == ref_invalid); 61 | } -------------------------------------------------------------------------------- /tests/csnode/stage_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | #include "gtest/gtest.h" 8 | 9 | 10 | TEST(StageOne, Constructors) { 11 | 12 | cs::StageOne fake; 13 | 14 | //init_zero(fake): 15 | fake.sender = 255; 16 | fake.hash.fill(0); 17 | fake.messageHash.fill(0); 18 | fake.signature.fill(0); 19 | fake.hashesCandidates.clear(); 20 | fake.trustedCandidates.clear(); 21 | fake.roundTimeStamp.clear(); 22 | 23 | fake.sender = 1U; 24 | fake.toBytes(); 25 | 26 | ASSERT_TRUE(fake.message.size() > 0); 27 | } 28 | TEST(StageTwo, Constructors) { 29 | 30 | cs::StageTwo fake; 31 | 32 | //init_zero(fake): 33 | fake.sender = cs::InvalidSender; 34 | fake.signature.fill(0); 35 | fake.hashes.resize(3, cs::Zero::hash); 36 | fake.signatures.resize(3, cs::Zero::signature); 37 | 38 | fake.sender = 1U; 39 | fake.toBytes(); 40 | 41 | ASSERT_TRUE(fake.message.size() > 0); 42 | } 43 | 44 | TEST(StageThree, Constructors) { 45 | 46 | cs::StageThree fake; 47 | fake.sender = 1U; 48 | fake.iteration = 0U; 49 | fake.blockSignature = cs::Zero::signature; 50 | fake.roundSignature = cs::Zero::signature; 51 | fake.trustedSignature = cs::Zero::signature; 52 | 53 | fake.toBytes(); 54 | 55 | ASSERT_TRUE(fake.message.size() > 0); 56 | } 57 | -------------------------------------------------------------------------------- /tests/csnode/thrift_api_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "gtest/gtest.h" 5 | 6 | TEST(ThriftAPI, SCISerialization) { 7 | ASSERT_NE(9, 0); 8 | 9 | //std::string bytes = cs::Utils::hexToString("610000000B0001000000087472616E736665720F00020C000000020B00110000002C33334A5778414D78587A4D6D7575416F425A7741666333714850367870315754696D6F46716B64564655776B000B00110000000131000F00030B000000000200040000"); 10 | //std::string bytes = cs::Utils::hexToString("0B0001000000087472616E736665720F00020C000000020B00110000002C33334A5778414D78587A4D6D7575416F425A7741666333714850367870315754696D6F46716B64564655776B000B00110000000131000F00030B000000000200040000"); 11 | //api::SmartContractInvocation sci = cs::Serializer::deserialize(std::move(bytes)); 12 | 13 | std::string bytez = cs::Utils::hexToString("0B0001000000087472616E736665720F00020C000000020B00110000002C33334A5778414D78587A4D6D7575416F425A7741666333714850367870315754696D6F46716B64564655776B000B00110000000131000F00030B0000000002000400060006000100"); 14 | api::SmartContractInvocation sci = cs::Serializer::deserialize(std::move(bytez)); 15 | } 16 | 17 | //TEST(ThriftAPI, TransactionSerialization) { 18 | // std::string bytes1 = cs::Utils::hexToString("0A000114000000000000001E4E57610E9461F703E3D0BEF1EC811A2DBA1D828B00B7AE2E793DBE398F8C63BC0B46FAA950462EA6FEF0311C292A4355FD92597C88D2FEA43FFF751682F57B000000000000000000000000664C0101610000000B0001000000087472616E736665720F00020C000000020B00110000002C33334A5778414D78587A4D6D7575416F425A7741666333714850367870315754696D6F46716B64564655776B000B00110000000131000F00030B000000000200040000"); 19 | // api::Transaction t1 = cs::Serializer::deserialize(std::move(bytes1)); 20 | // 21 | // std::string bytes2 = cs::Utils::hexToString("1400000000001E4E57610E9461F703E3D0BEF1EC811A2DBA1D828B00B7AE2E793DBE398F8C63BC0B46FAA950462EA6FEF0311C292A4355FD92597C88D2FEA43FFF751682F57B000000000000000000000000664C0101660000000B0001000000087472616E736665720F00020C000000020B00110000002C33334A5778414D78587A4D6D7575416F425A7741666333714850367870315754696D6F46716B64564655776B000B00110000000131000F00030B0000000002000400060006000100"); 22 | // api::Transaction t2 = cs::Serializer::deserialize(std::move(bytes2)); 23 | //} -------------------------------------------------------------------------------- /tests/csnode/transportmock.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by User on 03.10.2018. 3 | // 4 | 5 | #ifndef PROJECT_TRANSPORTMOCK_HPP 6 | #define PROJECT_TRANSPORTMOCK_HPP 7 | 8 | #include 9 | #include "transport.hpp" 10 | 11 | class TransportMock : public Transport { 12 | public: 13 | MOCK_METHOD0(run, void()); 14 | 15 | MOCK_METHOD1(processNodeMessage, void(const Packet&)); 16 | 17 | MOCK_CONST_METHOD0(getMyPublicKey, const cs::PublicKey&()); 18 | MOCK_CONST_METHOD0(isGood, bool()); 19 | 20 | MOCK_METHOD1(processPostponed, void(const cs::RoundNumber)); 21 | 22 | // private methods 23 | 24 | MOCK_METHOD3(postponePacket, void(const cs::RoundNumber, const MsgTypes, const Packet&)); 25 | 26 | MOCK_METHOD5(dispatchNodeMessage, 27 | void(const MsgTypes, const cs::RoundNumber, const Packet&, const uint8_t* data, size_t)); 28 | 29 | /* Network packages processing */ 30 | MOCK_METHOD0(gotPing, bool()); 31 | }; 32 | 33 | #endif // PROJECT_TRANSPORTMOCK_HPP 34 | -------------------------------------------------------------------------------- /tests/csnode/validator_tests.cpp: -------------------------------------------------------------------------------- 1 | #define TESTING 2 | 3 | #include 4 | #include 5 | #include "cscrypto/cryptotypes.hpp" 6 | #include "cscrypto/memoryprotection.hpp" 7 | #include 8 | 9 | #include 10 | #include "gtest/gtest.h" 11 | 12 | 13 | TEST(TransactionsValidator, multi) { 14 | 15 | using namespace cs; 16 | using PrivKey = cscrypto::ByteArray<64>; 17 | cs::Signature sig{}; 18 | 19 | cscrypto::Bytes bytes; 20 | DecodeBase58("CzvqNvaQpsE2v4FFTJ2mnTKu48JsMhLzzMALja8bt7DD", bytes); 21 | csdb::Address src = csdb::Address::from_public_key(bytes); 22 | DecodeBase58("G2GeLfwjg6XuvoWnZ7ssx9EPkEBqbYL3mw3fusgpzoBk", bytes); 23 | csdb::Address tgt = csdb::Address::from_public_key(bytes); 24 | DecodeBase58("4h6D57iTFE7883ZMMee7rW7LgLm6G46Jz4YVzrp91LfSxQGFxQnNF5QHqnrn4Q9KKVyXfRQJrCiM7rVtNHMPCcwM", bytes); 25 | ASSERT_TRUE(bytes.size() == 64); 26 | // basic transaction 27 | csdb::Transaction t(1LL, src, tgt, csdb::Currency{1}, csdb::Amount(1), csdb::AmountCommission(1.0), csdb::AmountCommission(0.0), sig); 28 | Reject::Reason r = Reject::Reason::None; 29 | WalletsState::WalletData wallState; 30 | wallState.balance_ = csdb::Amount{ 0 }; 31 | wallState.lastTrxInd_ = 0L; 32 | 33 | 34 | if (!wallState.trxTail_.isAllowed(t.innerID())) { 35 | r = wallState.trxTail_.isDuplicated(t.innerID()) ? Reject::Reason::DuplicatedInnerID : Reject::Reason::DisabledInnerID; 36 | ASSERT_FALSE(r == Reject::Reason::DuplicatedInnerID); 37 | ASSERT_FALSE(r == Reject::Reason::DisabledInnerID); 38 | } 39 | if (SmartContracts::is_executable(t)) { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/lib_system/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TEST_NAME system) 2 | 3 | file(GLOB SRCS *.cpp) 4 | add_executable(${TEST_NAME} ${SRCS}) 5 | 6 | target_link_libraries(${TEST_NAME} net gtest) 7 | 8 | set_property(TARGET ${TEST_NAME} PROPERTY CXX_STANDARD 17) 9 | set_property(TARGET ${TEST_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 10 | 11 | add_test(NAME ${TEST_NAME} 12 | COMMAND ${TEST_NAME}) 13 | 14 | configure_msvc_flags() 15 | -------------------------------------------------------------------------------- /tests/lib_system/main.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | int main(int argc, char **argv) { 4 | ::testing::InitGoogleTest(&argc, argv); 5 | int ret = RUN_ALL_TESTS(); 6 | return ret; 7 | } 8 | -------------------------------------------------------------------------------- /tests/lmdbxx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TEST_NAME lmdbxxtests) 2 | 3 | file(GLOB SRCS *.cpp) 4 | add_executable(${TEST_NAME} ${SRCS}) 5 | 6 | target_link_libraries(${TEST_NAME} ${LINKER_START_GROUP} lib gtest lmdbxx ${LINKER_END_GROUP}) 7 | target_include_directories(${TEST_NAME} PUBLIC 8 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/lib/system 9 | ) 10 | 11 | set_property(TARGET ${TEST_NAME} PROPERTY CXX_STANDARD 17) 12 | set_property(TARGET ${TEST_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | add_test(NAME ${TEST_NAME} 15 | COMMAND ${TEST_NAME}) 16 | 17 | configure_msvc_flags() 18 | -------------------------------------------------------------------------------- /tests/lmdbxx/main.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | int main(int argc, char **argv) { 4 | ::testing::InitGoogleTest(&argc, argv); 5 | int ret = RUN_ALL_TESTS(); 6 | return ret; 7 | } 8 | -------------------------------------------------------------------------------- /tests/testprogram/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TEST_NAME testprogram) 2 | 3 | file(GLOB SRCS *.cpp) 4 | add_executable(${TEST_NAME} ${SRCS}) 5 | 6 | set_property(TARGET ${TEST_NAME} PROPERTY CXX_STANDARD 17) 7 | set_property(TARGET ${TEST_NAME} PROPERTY CMAKE_CXX_STANDARD_REQUIRED ON) 8 | 9 | configure_msvc_flags() 10 | -------------------------------------------------------------------------------- /tests/testprogram/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | std::string code = { "0" }; 8 | std::string delay = { "10" }; 9 | 10 | if (argc > 1) { 11 | delay = std::string(argv[1]); 12 | } 13 | 14 | if (argc > 2) { 15 | code = std::string(argv[2]); 16 | } 17 | 18 | int c = std::stoi(code); 19 | int ms = std::stoi(delay); 20 | 21 | std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 22 | std::exit(c); 23 | } 24 | -------------------------------------------------------------------------------- /third-party/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | # default /W3 or /W4 for msvc at googletest 4 | add_subdirectory(googletest) 5 | add_subdirectory(thrift) 6 | 7 | configure_third_party_compiler_flags() 8 | 9 | add_subdirectory(berkeleydb) 10 | add_subdirectory(lz4) 11 | add_subdirectory(rang) 12 | add_subdirectory(nameof) 13 | -------------------------------------------------------------------------------- /third-party/lz4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project (lz4) 4 | 5 | add_library(${PROJECT_NAME} 6 | lz4.h 7 | lz4.c ) 8 | -------------------------------------------------------------------------------- /third-party/rang/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project (rang) 4 | 5 | add_library(${PROJECT_NAME} INTERFACE) 6 | 7 | target_include_directories(rang INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) 8 | --------------------------------------------------------------------------------