From ceffe4cf3c5c6821664d4d3f35a8954622d42a97 Mon Sep 17 00:00:00 2001 From: serkixenos Date: Thu, 18 Nov 2021 17:32:30 +0000 Subject: [PATCH] SON for Hive --- .gitignore | 1 + README.md | 1 - bkup_CMakeCache.txt | 794 -------------- clang-format.sh | 4 + libraries/chain/db_maint.cpp | 117 ++- libraries/chain/hardfork.d/SON_FOR_HIVE.hf | 4 + .../chain/protocol/chain_parameters.hpp | 10 + .../include/graphene/chain/sidechain_defs.hpp | 4 +- .../chain/sidechain_transaction_object.hpp | 2 + .../include/graphene/chain/son_object.hpp | 8 +- libraries/chain/protocol/memo.cpp | 4 +- .../chain/sidechain_address_evaluator.cpp | 8 +- .../chain/sidechain_transaction_evaluator.cpp | 11 +- libraries/chain/son_object.cpp | 4 +- .../chain/son_wallet_deposit_evaluator.cpp | 16 +- .../chain/son_wallet_withdraw_evaluator.cpp | 16 +- .../peerplays_sidechain/CMakeLists.txt | 9 +- .../bitcoin/bitcoin_script.cpp | 2 +- .../peerplays_sidechain/common/rpc_client.cpp | 185 ++++ .../peerplays_sidechain/common/utils.cpp | 8 + .../peerplays_sidechain/hive/asset.cpp | 69 ++ .../peerplays_sidechain/hive/operations.cpp | 101 ++ .../peerplays_sidechain/hive/transaction.cpp | 57 + .../peerplays_sidechain/hive/types.cpp | 73 ++ .../peerplays_sidechain/common/rpc_client.hpp | 39 + .../peerplays_sidechain/common/utils.hpp | 5 + .../peerplays_sidechain/hive/asset.hpp | 41 + .../peerplays_sidechain/hive/authority.hpp | 33 + .../hive/hive_operations.hpp | 123 +++ .../peerplays_sidechain/hive/operations.hpp | 69 ++ .../peerplays_sidechain/hive/transaction.hpp | 44 + .../peerplays_sidechain/hive/types.hpp | 72 ++ .../peerplays_sidechain_plugin.hpp | 1 + .../sidechain_net_handler.hpp | 7 +- .../sidechain_net_handler_bitcoin.hpp | 14 +- .../sidechain_net_handler_hive.hpp | 68 ++ .../sidechain_net_handler_peerplays.hpp | 5 +- .../sidechain_net_manager.hpp | 2 + .../peerplays_sidechain_plugin.cpp | 92 +- .../sidechain_net_handler.cpp | 150 ++- .../sidechain_net_handler_bitcoin.cpp | 106 +- .../sidechain_net_handler_hive.cpp | 971 ++++++++++++++++++ .../sidechain_net_handler_peerplays.cpp | 109 +- .../sidechain_net_manager.cpp | 14 + .../wallet/include/graphene/wallet/wallet.hpp | 56 +- libraries/wallet/wallet.cpp | 56 +- tests/cli/son.cpp | 15 + tests/tests/son_operations_tests.cpp | 44 +- 48 files changed, 2626 insertions(+), 1018 deletions(-) delete mode 100644 bkup_CMakeCache.txt create mode 100755 clang-format.sh create mode 100644 libraries/chain/hardfork.d/SON_FOR_HIVE.hf create mode 100644 libraries/plugins/peerplays_sidechain/common/rpc_client.cpp create mode 100644 libraries/plugins/peerplays_sidechain/common/utils.cpp create mode 100644 libraries/plugins/peerplays_sidechain/hive/asset.cpp create mode 100644 libraries/plugins/peerplays_sidechain/hive/operations.cpp create mode 100644 libraries/plugins/peerplays_sidechain/hive/transaction.cpp create mode 100644 libraries/plugins/peerplays_sidechain/hive/types.cpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp create mode 100644 libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp diff --git a/.gitignore b/.gitignore index 39b23163..1a84b559 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ data CMakeDoxyfile.in build +build__* libraries/utilities/git_revision.cpp diff --git a/README.md b/README.md index 7173bcb1..e1ad6ef0 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,6 @@ make -j$(nproc) make install # this can install the executable files under /usr/local ``` -docker build -t peerplays . ## Docker image diff --git a/bkup_CMakeCache.txt b/bkup_CMakeCache.txt deleted file mode 100644 index daa267e9..00000000 --- a/bkup_CMakeCache.txt +++ /dev/null @@ -1,794 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /home/pbattu/git/18.04/peerplays -# It was generated by CMake: /usr/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//No help, variable specified on the command line. -BOOST_ROOT:PATH=/home/pbattu/git/18.04/boost_1_67_0 - -//The threading library used by boost-thread -BOOST_THREAD_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpthread.so - -//Build bitshares executables (witness node, cli wallet, etc) -BUILD_BITSHARES_PROGRAMS:BOOL=TRUE - -//Build bitshares unit tests -BUILD_BITSHARES_TESTS:BOOL=TRUE - -//Build websocketpp examples. -BUILD_EXAMPLES:BOOL=OFF - -//Build websocketpp tests. -BUILD_TESTS:BOOL=OFF - -//Value Computed by CMake -BitShares_BINARY_DIR:STATIC=/home/pbattu/git/18.04/peerplays - -//Value Computed by CMake -BitShares_SOURCE_DIR:STATIC=/home/pbattu/git/18.04/peerplays - -//Boost chrono library (debug) -Boost_CHRONO_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_chrono.a - -//Boost chrono library (release) -Boost_CHRONO_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_chrono.a - -//Boost context library (debug) -Boost_CONTEXT_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_context.a - -//Boost context library (release) -Boost_CONTEXT_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_context.a - -//Boost coroutine library (debug) -Boost_COROUTINE_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_coroutine.a - -//Boost coroutine library (release) -Boost_COROUTINE_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_coroutine.a - -//Boost date_time library (debug) -Boost_DATE_TIME_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_date_time.a - -//Boost date_time library (release) -Boost_DATE_TIME_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_date_time.a - -//The directory containing a CMake configuration file for Boost. -Boost_DIR:PATH=Boost_DIR-NOTFOUND - -//Boost filesystem library (debug) -Boost_FILESYSTEM_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_filesystem.a - -//Boost filesystem library (release) -Boost_FILESYSTEM_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_filesystem.a - -//Path to a file. -Boost_INCLUDE_DIR:PATH=/home/pbattu/git/18.04/boost_1_67_0/include - -//Boost iostreams library (debug) -Boost_IOSTREAMS_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_iostreams.a - -//Boost iostreams library (release) -Boost_IOSTREAMS_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_iostreams.a - -//Boost library directory -Boost_LIBRARY_DIR:PATH=/home/pbattu/git/18.04/boost_1_67_0/lib - -//Boost library directory DEBUG -Boost_LIBRARY_DIR_DEBUG:PATH=/home/pbattu/git/18.04/boost_1_67_0/lib - -//Boost library directory RELEASE -Boost_LIBRARY_DIR_RELEASE:PATH=/home/pbattu/git/18.04/boost_1_67_0/lib - -//Boost locale library (debug) -Boost_LOCALE_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_locale.a - -//Boost locale library (release) -Boost_LOCALE_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_locale.a - -//Boost program_options library (debug) -Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_program_options.a - -//Boost program_options library (release) -Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_program_options.a - -//Boost serialization library (debug) -Boost_SERIALIZATION_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_serialization.a - -//Boost serialization library (release) -Boost_SERIALIZATION_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_serialization.a - -//Boost signals library (debug) -Boost_SIGNALS_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_signals.a - -//Boost signals library (release) -Boost_SIGNALS_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_signals.a - -//Boost system library (debug) -Boost_SYSTEM_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_system.a - -//Boost system library (release) -Boost_SYSTEM_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_system.a - -//Boost thread library (debug) -Boost_THREAD_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_thread.a - -//Boost thread library (release) -Boost_THREAD_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_thread.a - -//Boost unit_test_framework library (debug) -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_unit_test_framework.a - -//Boost unit_test_framework library (release) -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE:FILEPATH=/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_unit_test_framework.a - -//ON or OFF -Boost_USE_STATIC_LIBS:STRING=ON - -//Path to a program. -CMAKE_AR:FILEPATH=/usr/bin/ar - -//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or -// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. -CMAKE_BUILD_TYPE:STRING=Debug - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//Configurations -CMAKE_CONFIGURATION_TYPES:STRING=Release;RelWithDebInfo;Debug - -//CXX compiler -CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-5 - -//A wrapper around 'ar' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-5 - -//A wrapper around 'ranlib' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-5 - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//C compiler -CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-5 - -//A wrapper around 'ar' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-5 - -//A wrapper around 'ranlib' adding the appropriate '--plugin' option -// for the GCC compiler -CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-5 - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Enable/Disable output of compile commands during generation. -CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//Path to a program. -CMAKE_LINKER:FILEPATH=/usr/bin/ld - -//Path to a program. -CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/usr/bin/nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=BitShares - -//Path to a program. -CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_STRIP:FILEPATH=/usr/bin/strip - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Path to a library. -CURSES_CURSES_LIBRARY:FILEPATH=CURSES_CURSES_LIBRARY-NOTFOUND - -//Path to a library. -CURSES_FORM_LIBRARY:FILEPATH=CURSES_FORM_LIBRARY-NOTFOUND - -//Path to a file. -CURSES_INCLUDE_PATH:PATH=CURSES_INCLUDE_PATH-NOTFOUND - -//Path to a library. -CURSES_NCURSES_LIBRARY:FILEPATH=CURSES_NCURSES_LIBRARY-NOTFOUND - -//Dot tool for use with Doxygen -DOXYGEN_DOT_EXECUTABLE:FILEPATH=DOXYGEN_DOT_EXECUTABLE-NOTFOUND - -//Doxygen documentation generation tool (http://www.doxygen.org) -DOXYGEN_EXECUTABLE:FILEPATH=DOXYGEN_EXECUTABLE-NOTFOUND - -//secp256k1 or openssl or mixed -ECC_IMPL:STRING=secp256k1 - -//Build BitShares for code coverage analysis -ENABLE_COVERAGE_TESTING:BOOL=FALSE - -//Build websocketpp with CPP11 features enabled. -ENABLE_CPP11:BOOL=ON - -//TRUE to try to use full zlib for compression, FALSE to use miniz.c -FC_USE_FULL_ZLIB:BOOL=FALSE - -//Git command line client -GIT_EXECUTABLE:FILEPATH=/usr/bin/git - -//location of the genesis.json to embed in the executable -GRAPHENE_EGENESIS_JSON:PATH=/home/pbattu/git/18.04/peerplays/genesis.json - -//The directory containing a CMake configuration file for Gperftools. -Gperftools_DIR:PATH=Gperftools_DIR-NOTFOUND - -//Installation directory for CMake files -INSTALL_CMAKE_DIR:PATH=lib/cmake/websocketpp - -//Installation directory for header files -INSTALL_INCLUDE_DIR:PATH=include - -//Log long API calls over websocket (ON OR OFF) -LOG_LONG_API:BOOL=ON - -//Max API execution time in ms -LOG_LONG_API_MAX_MS:STRING=1000 - -//API execution time in ms at which to warn -LOG_LONG_API_WARN_MS:STRING=750 - -//Path to a library. -OPENSSL_CRYPTO_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libcrypto.a - -//Path to a file. -OPENSSL_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -OPENSSL_SSL_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libssl.a - -//Path to a program. -PERL_EXECUTABLE:FILEPATH=/usr/bin/perl - -//pkg-config executable -PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config - -//Path to a file. -READLINE_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -READLINE_LIBRARIES:FILEPATH=/usr/lib/x86_64-linux-gnu/libreadline.so - -//Path to a file. -Readline_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -Readline_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libreadline.so - -//Path to a file. -Readline_ROOT_DIR:PATH=/usr - -//OFF -UNITY_BUILD:BOOL=OFF - -//Path to a file. -ZLIB_INCLUDE_DIR:PATH=/usr/include - -//Path to a library. -ZLIB_LIBRARY_DEBUG:FILEPATH=ZLIB_LIBRARY_DEBUG-NOTFOUND - -//Path to a library. -ZLIB_LIBRARY_RELEASE:FILEPATH=/usr/lib/x86_64-linux-gnu/libz.so - -//Value Computed by CMake -fc_BINARY_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc - -//Dependencies for the target -fc_LIB_DEPENDS:STATIC=general;-L/usr/local/lib;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_thread.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_date_time.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_filesystem.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_system.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_program_options.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_signals.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_serialization.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_chrono.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_unit_test_framework.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_context.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_locale.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_iostreams.a;general;/home/pbattu/git/18.04/boost_1_67_0/lib/libboost_coroutine.a;general;/usr/lib/x86_64-linux-gnu/libpthread.so;general;/usr/lib/x86_64-linux-gnu/libssl.a;general;/usr/lib/x86_64-linux-gnu/libcrypto.a;general;/usr/lib/x86_64-linux-gnu/libz.so;general;dl;general;rt;general;/usr/lib/x86_64-linux-gnu/libreadline.so;general;secp256k1; - -//Value Computed by CMake -fc_SOURCE_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc - -//Dependencies for the target -graphene_account_history_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_accounts_list_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_affiliate_stats_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_app_LIB_DEPENDS:STATIC=general;graphene_market_history;general;graphene_account_history;general;graphene_accounts_list;general;graphene_affiliate_stats;general;graphene_chain;general;fc;general;graphene_db;general;graphene_net;general;graphene_time;general;graphene_utilities;general;graphene_debug_witness;general;graphene_bookie; - -//Dependencies for the target -graphene_bookie_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_chain_LIB_DEPENDS:STATIC=general;fc;general;graphene_db; - -//Dependencies for the target -graphene_db_LIB_DEPENDS:STATIC=general;fc; - -//Dependencies for the target -graphene_debug_witness_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_delayed_node_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_egenesis_brief_LIB_DEPENDS:STATIC=general;graphene_chain;general;fc; - -//Dependencies for the target -graphene_egenesis_full_LIB_DEPENDS:STATIC=general;graphene_chain;general;fc; - -//Dependencies for the target -graphene_egenesis_none_LIB_DEPENDS:STATIC=general;graphene_chain;general;fc; - -//Dependencies for the target -graphene_generate_genesis_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app;general;graphene_time; - -//Dependencies for the target -graphene_generate_uia_sharedrop_genesis_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app;general;graphene_time; - -//Dependencies for the target -graphene_market_history_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_net_LIB_DEPENDS:STATIC=general;fc;general;graphene_db; - -//Dependencies for the target -graphene_snapshot_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Dependencies for the target -graphene_time_LIB_DEPENDS:STATIC=general;fc; - -//Dependencies for the target -graphene_utilities_LIB_DEPENDS:STATIC=general;fc; - -//Dependencies for the target -graphene_wallet_LIB_DEPENDS:STATIC=general;graphene_app;general;graphene_net;general;graphene_chain;general;graphene_utilities;general;fc;general;dl; - -//Dependencies for the target -graphene_witness_LIB_DEPENDS:STATIC=general;graphene_chain;general;graphene_app; - -//Value Computed by CMake -websocketpp_BINARY_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc/vendor/websocketpp - -//Value Computed by CMake -websocketpp_SOURCE_DIR:STATIC=/home/pbattu/git/18.04/peerplays/libraries/fc/vendor/websocketpp - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: BOOST_ROOT -BOOST_ROOT-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CHRONO_LIBRARY_DEBUG -Boost_CHRONO_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CHRONO_LIBRARY_RELEASE -Boost_CHRONO_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CONTEXT_LIBRARY_DEBUG -Boost_CONTEXT_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_CONTEXT_LIBRARY_RELEASE -Boost_CONTEXT_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_COROUTINE_LIBRARY_DEBUG -Boost_COROUTINE_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_COROUTINE_LIBRARY_RELEASE -Boost_COROUTINE_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_DATE_TIME_LIBRARY_DEBUG -Boost_DATE_TIME_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_DATE_TIME_LIBRARY_RELEASE -Boost_DATE_TIME_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_DIR -Boost_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_FILESYSTEM_LIBRARY_DEBUG -Boost_FILESYSTEM_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_FILESYSTEM_LIBRARY_RELEASE -Boost_FILESYSTEM_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_INCLUDE_DIR -Boost_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_IOSTREAMS_LIBRARY_DEBUG -Boost_IOSTREAMS_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_IOSTREAMS_LIBRARY_RELEASE -Boost_IOSTREAMS_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LIBRARY_DIR -Boost_LIBRARY_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LIBRARY_DIR_DEBUG -Boost_LIBRARY_DIR_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LIBRARY_DIR_RELEASE -Boost_LIBRARY_DIR_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LOCALE_LIBRARY_DEBUG -Boost_LOCALE_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_LOCALE_LIBRARY_RELEASE -Boost_LOCALE_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG -Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE -Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SERIALIZATION_LIBRARY_DEBUG -Boost_SERIALIZATION_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SERIALIZATION_LIBRARY_RELEASE -Boost_SERIALIZATION_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SIGNALS_LIBRARY_DEBUG -Boost_SIGNALS_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SIGNALS_LIBRARY_RELEASE -Boost_SIGNALS_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SYSTEM_LIBRARY_DEBUG -Boost_SYSTEM_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_SYSTEM_LIBRARY_RELEASE -Boost_SYSTEM_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_THREAD_LIBRARY_DEBUG -Boost_THREAD_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_THREAD_LIBRARY_RELEASE -Boost_THREAD_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE -Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/home/pbattu/git/18.04/peerplays -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=10 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 -//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE -CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/usr/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER -CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR -CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB -CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER -CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_AR -CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB -CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS -CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Unix Makefiles -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Have symbol pthread_create -CMAKE_HAVE_LIBC_CREATE:INTERNAL= -//Have library pthreads -CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= -//Have library pthread -CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 -//Have include pthread.h -CMAKE_HAVE_PTHREAD_H:INTERNAL=1 -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/home/pbattu/git/18.04/peerplays -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=37 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.10 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//uname command -CMAKE_UNAME:INTERNAL=/bin/uname -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_CURSES_LIBRARY -CURSES_CURSES_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_FORM_LIBRARY -CURSES_FORM_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_INCLUDE_PATH -CURSES_INCLUDE_PATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CURSES_NCURSES_LIBRARY -CURSES_NCURSES_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: DOXYGEN_DOT_EXECUTABLE -DOXYGEN_DOT_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: DOXYGEN_EXECUTABLE -DOXYGEN_EXECUTABLE-ADVANCED:INTERNAL=1 -//Details about finding OpenSSL -FIND_PACKAGE_MESSAGE_DETAILS_OpenSSL:INTERNAL=[/usr/lib/x86_64-linux-gnu/libcrypto.a][/usr/include][v1.1.0g()] -//Details about finding Perl -FIND_PACKAGE_MESSAGE_DETAILS_Perl:INTERNAL=[/usr/bin/perl][v5.26.1()] -//Details about finding Readline -FIND_PACKAGE_MESSAGE_DETAILS_Readline:INTERNAL=[/usr/include][/usr/lib/x86_64-linux-gnu/libreadline.so][v()] -//Details about finding Threads -FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] -//Details about finding ZLIB -FIND_PACKAGE_MESSAGE_DETAILS_ZLIB:INTERNAL=[/usr/lib/x86_64-linux-gnu/libz.so][/usr/include][v1.2.11()] -//ADVANCED property for variable: GIT_EXECUTABLE -GIT_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENSSL_CRYPTO_LIBRARY -OPENSSL_CRYPTO_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENSSL_INCLUDE_DIR -OPENSSL_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENSSL_SSL_LIBRARY -OPENSSL_SSL_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PERL_EXECUTABLE -PERL_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: PKG_CONFIG_EXECUTABLE -PKG_CONFIG_EXECUTABLE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Readline_INCLUDE_DIR -Readline_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Readline_LIBRARY -Readline_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Readline_ROOT_DIR -Readline_ROOT_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_INCLUDE_DIR -ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_DEBUG -ZLIB_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_RELEASE -ZLIB_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//Last used BOOST_ROOT value. -_BOOST_ROOT_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0 -//Components requested for this build tree. -_Boost_COMPONENTS_SEARCHED:INTERNAL=chrono;context;coroutine;date_time;filesystem;iostreams;locale;program_options;serialization;signals;system;thread;unit_test_framework -//Last used Boost_INCLUDE_DIR value. -_Boost_INCLUDE_DIR_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/include -//Last used Boost_LIBRARY_DIR_DEBUG value. -_Boost_LIBRARY_DIR_DEBUG_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/lib -//Last used Boost_LIBRARY_DIR value. -_Boost_LIBRARY_DIR_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/lib -//Last used Boost_LIBRARY_DIR_RELEASE value. -_Boost_LIBRARY_DIR_RELEASE_LAST:INTERNAL=/home/pbattu/git/18.04/boost_1_67_0/lib -//Last used Boost_NAMESPACE value. -_Boost_NAMESPACE_LAST:INTERNAL=boost -//Last used Boost_USE_MULTITHREADED value. -_Boost_USE_MULTITHREADED_LAST:INTERNAL=TRUE -//Last used Boost_USE_STATIC_LIBS value. -_Boost_USE_STATIC_LIBS_LAST:INTERNAL=ON -_OPENSSL_CFLAGS:INTERNAL= -_OPENSSL_CFLAGS_I:INTERNAL= -_OPENSSL_CFLAGS_OTHER:INTERNAL= -_OPENSSL_FOUND:INTERNAL=1 -_OPENSSL_INCLUDEDIR:INTERNAL=/usr/include -_OPENSSL_INCLUDE_DIRS:INTERNAL= -_OPENSSL_LDFLAGS:INTERNAL=-lssl;-lcrypto -_OPENSSL_LDFLAGS_OTHER:INTERNAL= -_OPENSSL_LIBDIR:INTERNAL=/usr/lib/x86_64-linux-gnu -_OPENSSL_LIBRARIES:INTERNAL=ssl;crypto -_OPENSSL_LIBRARY_DIRS:INTERNAL= -_OPENSSL_LIBS:INTERNAL= -_OPENSSL_LIBS_L:INTERNAL= -_OPENSSL_LIBS_OTHER:INTERNAL= -_OPENSSL_LIBS_PATHS:INTERNAL= -_OPENSSL_PREFIX:INTERNAL=/usr -_OPENSSL_STATIC_CFLAGS:INTERNAL= -_OPENSSL_STATIC_CFLAGS_I:INTERNAL= -_OPENSSL_STATIC_CFLAGS_OTHER:INTERNAL= -_OPENSSL_STATIC_INCLUDE_DIRS:INTERNAL= -_OPENSSL_STATIC_LDFLAGS:INTERNAL=-lssl;-ldl;-lcrypto;-ldl -_OPENSSL_STATIC_LDFLAGS_OTHER:INTERNAL= -_OPENSSL_STATIC_LIBDIR:INTERNAL= -_OPENSSL_STATIC_LIBRARIES:INTERNAL=ssl;dl;crypto;dl -_OPENSSL_STATIC_LIBRARY_DIRS:INTERNAL= -_OPENSSL_STATIC_LIBS:INTERNAL= -_OPENSSL_STATIC_LIBS_L:INTERNAL= -_OPENSSL_STATIC_LIBS_OTHER:INTERNAL= -_OPENSSL_STATIC_LIBS_PATHS:INTERNAL= -_OPENSSL_VERSION:INTERNAL=1.1.0g -_OPENSSL_openssl_INCLUDEDIR:INTERNAL= -_OPENSSL_openssl_LIBDIR:INTERNAL= -_OPENSSL_openssl_PREFIX:INTERNAL= -_OPENSSL_openssl_VERSION:INTERNAL= -__pkg_config_arguments__OPENSSL:INTERNAL=QUIET;openssl -__pkg_config_checked__OPENSSL:INTERNAL=1 -prefix_result:INTERNAL=/usr/lib/x86_64-linux-gnu - diff --git a/clang-format.sh b/clang-format.sh new file mode 100755 index 00000000..6ab95eb9 --- /dev/null +++ b/clang-format.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +find ./libraries/plugins/peerplays_sidechain -regex ".*[c|h]pp" | xargs clang-format -i + diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 2e945756..fc931113 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -210,20 +210,29 @@ void database::pay_sons() if( now < HARDFORK_SON2_TIME ) { son_weight = get_weight_before_son2_hf(_vote_tally_buffer[son_obj->vote_id]); } - weighted_total_txs_signed += (s.txs_signed * son_weight); + uint64_t txs_signed = 0; + for (const auto &ts : s.txs_signed) { + txs_signed = txs_signed + ts.second; + } + weighted_total_txs_signed += (txs_signed * son_weight); }); // Now pay off each SON proportional to the number of transactions signed. get_index_type().inspect_all_objects([this, &weighted_total_txs_signed, &dpo, &son_budget, &get_weight, &get_weight_before_son2_hf, &now](const object& o) { const son_statistics_object& s = static_cast(o); - if(s.txs_signed > 0){ + uint64_t txs_signed = 0; + for (const auto &ts : s.txs_signed) { + txs_signed = txs_signed + ts.second; + } + + if(txs_signed > 0){ const auto& idx = get_index_type().indices().get(); auto son_obj = idx.find( s.owner ); auto son_weight = get_weight(_vote_tally_buffer[son_obj->vote_id]); if( now < HARDFORK_SON2_TIME ) { son_weight = get_weight_before_son2_hf(_vote_tally_buffer[son_obj->vote_id]); } - share_type pay = (s.txs_signed * son_weight * son_budget.value)/weighted_total_txs_signed; + share_type pay = (txs_signed * son_weight * son_budget.value)/weighted_total_txs_signed; modify( *son_obj, [&]( son_object& _son_obj) { _son_obj.pay_son_fee(pay, *this); @@ -236,8 +245,9 @@ void database::pay_sons() //Reset the tx counter in each son statistics object modify( s, [&]( son_statistics_object& _s) { - _s.total_txs_signed += _s.txs_signed; - _s.txs_signed = 0; + for (const auto &ts : s.txs_signed) { + _s.txs_signed.at(ts.first) = 0; + } }); } }); @@ -267,11 +277,13 @@ void database::update_son_metrics(const vector& curr_active_sons) bool is_active_son = (std::find(current_sons.begin(), current_sons.end(), son.id) != current_sons.end()); modify( stats, [&]( son_statistics_object& _stats ) { + if(is_active_son) { + _stats.total_voted_time = _stats.total_voted_time + get_global_properties().parameters.maintenance_interval; + } _stats.total_downtime += _stats.current_interval_downtime; _stats.current_interval_downtime = 0; - if(is_active_son) - { - _stats.total_voted_time = _stats.total_voted_time + get_global_properties().parameters.maintenance_interval; + for (const auto &str : _stats.sidechain_txs_reported) { + _stats.sidechain_txs_reported.at(str.first) = 0; } }); } @@ -593,7 +605,7 @@ void database::update_active_committee_members() update_committee_member_total_votes( cm ); } } - + // Update committee authorities if( !committee_members.empty() ) { @@ -1243,13 +1255,13 @@ double database::calculate_vesting_factor(const account_object& stake_account) // variables needed const auto number_of_subperiods = vesting_period / vesting_subperiod; double vesting_factor; - + // get in what sub period we are uint32_t current_subperiod = get_gpos_current_subperiod(); - + if(current_subperiod == 0 || current_subperiod > number_of_subperiods) return 0; - // On starting new vesting period, all votes become zero until someone votes, To avoid a situation of zero votes, + // On starting new vesting period, all votes become zero until someone votes, To avoid a situation of zero votes, // changes were done to roll in GPOS rules, the vesting factor will be 1 for whoever votes in 6th sub-period of last vesting period // BLOCKBACK-174 fix if(current_subperiod == 1 && this->head_block_time() >= HARDFORK_GPOS_TIME + vesting_period) //Applicable only from 2nd vesting period @@ -1925,10 +1937,7 @@ void database::perform_son_tasks() a.options.market_fee_percent = 500; // 5% a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; a.options.flags = asset_issuer_permission_flags::charge_market_fee | - //asset_issuer_permission_flags::white_list | - asset_issuer_permission_flags::override_authority | - asset_issuer_permission_flags::transfer_restricted | - asset_issuer_permission_flags::disable_confidential; + asset_issuer_permission_flags::override_authority; a.options.core_exchange_rate.base.amount = 100000; a.options.core_exchange_rate.base.asset_id = asset_id_type(0); a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value @@ -1945,6 +1954,74 @@ void database::perform_son_tasks() gpo.pending_parameters->extensions.value.btc_asset = btc_asset.get_id(); }); } + // create HBD asset here because son_account is the issuer of the HBD + if (gpo.parameters.hbd_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_FOR_HIVE_TIME) + { + const asset_dynamic_data_object& dyn_asset = + create([](asset_dynamic_data_object& a) { + a.current_supply = 0; + }); + + const asset_object& hbd_asset = + create( [&gpo, &dyn_asset]( asset_object& a ) { + a.symbol = "HBD"; + a.precision = 3; + a.issuer = gpo.parameters.son_account(); + a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + a.options.market_fee_percent = 500; // 5% + a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; + a.options.flags = asset_issuer_permission_flags::charge_market_fee | + asset_issuer_permission_flags::override_authority; + a.options.core_exchange_rate.base.amount = 100000; + a.options.core_exchange_rate.base.asset_id = asset_id_type(0); + a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value + a.options.core_exchange_rate.quote.asset_id = a.id; + a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty + a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set + a.options.whitelist_markets.clear(); // might be traded with + a.options.blacklist_markets.clear(); // might not be traded with + a.dynamic_asset_data_id = dyn_asset.id; + }); + modify( gpo, [&hbd_asset]( global_property_object& gpo ) { + gpo.parameters.extensions.value.hbd_asset = hbd_asset.get_id(); + if( gpo.pending_parameters ) + gpo.pending_parameters->extensions.value.hbd_asset = hbd_asset.get_id(); + }); + } + // create HIVE asset here because son_account is the issuer of the HIVE + if (gpo.parameters.hive_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_TIME) + { + const asset_dynamic_data_object& dyn_asset = + create([](asset_dynamic_data_object& a) { + a.current_supply = 0; + }); + + const asset_object& hive_asset = + create( [&gpo, &dyn_asset]( asset_object& a ) { + a.symbol = "HIVE"; + a.precision = 3; + a.issuer = gpo.parameters.son_account(); + a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + a.options.market_fee_percent = 500; // 5% + a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; + a.options.flags = asset_issuer_permission_flags::charge_market_fee | + asset_issuer_permission_flags::override_authority; + a.options.core_exchange_rate.base.amount = 100000; + a.options.core_exchange_rate.base.asset_id = asset_id_type(0); + a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value + a.options.core_exchange_rate.quote.asset_id = a.id; + a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty + a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set + a.options.whitelist_markets.clear(); // might be traded with + a.options.blacklist_markets.clear(); // might not be traded with + a.dynamic_asset_data_id = dyn_asset.id; + }); + modify( gpo, [&hive_asset]( global_property_object& gpo ) { + gpo.parameters.extensions.value.hive_asset = hive_asset.get_id(); + if( gpo.pending_parameters ) + gpo.pending_parameters->extensions.value.hive_asset = hive_asset.get_id(); + }); + } // Pay the SONs if (head_block_time() >= HARDFORK_SON_TIME) { @@ -2114,7 +2191,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g } } } tally_helper(*this, gpo); - + perform_account_maintenance( tally_helper ); struct clear_canary { clear_canary(vector& target): target(target){} @@ -2160,7 +2237,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g if( !p.pending_parameters->extensions.value.gpos_subperiod.valid() ) p.pending_parameters->extensions.value.gpos_subperiod = p.parameters.extensions.value.gpos_subperiod; if( !p.pending_parameters->extensions.value.gpos_vesting_lockin_period.valid() ) - p.pending_parameters->extensions.value.gpos_vesting_lockin_period = p.parameters.extensions.value.gpos_vesting_lockin_period; + p.pending_parameters->extensions.value.gpos_vesting_lockin_period = p.parameters.extensions.value.gpos_vesting_lockin_period; if( !p.pending_parameters->extensions.value.rbac_max_permissions_per_account.valid() ) p.pending_parameters->extensions.value.rbac_max_permissions_per_account = p.parameters.extensions.value.rbac_max_permissions_per_account; if( !p.pending_parameters->extensions.value.rbac_max_account_authority_lifetime.valid() ) @@ -2193,6 +2270,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g p.pending_parameters->extensions.value.btc_asset = p.parameters.extensions.value.btc_asset; if( !p.pending_parameters->extensions.value.maximum_son_count.valid() ) p.pending_parameters->extensions.value.maximum_son_count = p.parameters.extensions.value.maximum_son_count; + if( !p.pending_parameters->extensions.value.hbd_asset.valid() ) + p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset; + if( !p.pending_parameters->extensions.value.hive_asset.valid() ) + p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset; p.parameters = std::move(*p.pending_parameters); p.pending_parameters.reset(); } diff --git a/libraries/chain/hardfork.d/SON_FOR_HIVE.hf b/libraries/chain/hardfork.d/SON_FOR_HIVE.hf new file mode 100644 index 00000000..76ba2b56 --- /dev/null +++ b/libraries/chain/hardfork.d/SON_FOR_HIVE.hf @@ -0,0 +1,4 @@ +// Wednesday, March 31, 2021 0:00:00 +#ifndef HARDFORK_SON_FOR_HIVE_TIME +#define HARDFORK_SON_FOR_HIVE_TIME (fc::time_point_sec( 1617148800 )) +#endif diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index c24a0576..3a11e99f 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -68,6 +68,8 @@ namespace graphene { namespace chain { optional < account_id_type > son_account = GRAPHENE_NULL_ACCOUNT; optional < asset_id_type > btc_asset = asset_id_type(); optional < uint16_t > maximum_son_count = GRAPHENE_DEFAULT_MAX_SONS; ///< maximum number of active SONS + optional < asset_id_type > hbd_asset = asset_id_type(); + optional < asset_id_type > hive_asset = asset_id_type(); }; struct chain_parameters @@ -212,6 +214,12 @@ namespace graphene { namespace chain { inline uint16_t maximum_son_count()const { return extensions.value.maximum_son_count.valid() ? *extensions.value.maximum_son_count : GRAPHENE_DEFAULT_MAX_SONS; } + inline asset_id_type hbd_asset() const { + return extensions.value.hbd_asset.valid() ? *extensions.value.hbd_asset : asset_id_type(); + } + inline asset_id_type hive_asset() const { + return extensions.value.hive_asset.valid() ? *extensions.value.hive_asset : asset_id_type(); + } private: static void safe_copy(chain_parameters& to, const chain_parameters& from); }; @@ -247,6 +255,8 @@ FC_REFLECT( graphene::chain::parameter_extension, (son_account) (btc_asset) (maximum_son_count) + (hbd_asset) + (hive_asset) ) FC_REFLECT( graphene::chain::chain_parameters, diff --git a/libraries/chain/include/graphene/chain/sidechain_defs.hpp b/libraries/chain/include/graphene/chain/sidechain_defs.hpp index 6bbc8b5c..7f986f96 100644 --- a/libraries/chain/include/graphene/chain/sidechain_defs.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_defs.hpp @@ -9,7 +9,8 @@ enum class sidechain_type { bitcoin, ethereum, eos, - peerplays + peerplays, + hive }; } } @@ -19,4 +20,5 @@ FC_REFLECT_ENUM(graphene::chain::sidechain_type, (bitcoin) (ethereum) (eos) + (hive) (peerplays) ) diff --git a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp index da39f636..30a0dd5e 100644 --- a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp @@ -26,6 +26,7 @@ namespace graphene { namespace chain { static const uint8_t space_id = protocol_ids; static const uint8_t type_id = sidechain_transaction_object_type; + time_point_sec timestamp; sidechain_type sidechain = sidechain_type::unknown; object_id_type object_id; std::string transaction; @@ -70,6 +71,7 @@ FC_REFLECT_ENUM( graphene::chain::sidechain_transaction_status, (settled) ) FC_REFLECT_DERIVED( graphene::chain::sidechain_transaction_object, (graphene::db::object ), + (timestamp) (sidechain) (object_id) (transaction) diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 53072515..8c0e32dc 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -31,9 +31,9 @@ namespace graphene { namespace chain { son_id_type owner; // Lifetime total transactions signed - uint64_t total_txs_signed = 0; + flat_map total_txs_signed; // Transactions signed since the last son payouts - uint64_t txs_signed = 0; + flat_map txs_signed; // Total Voted Active time i.e. duration selected as part of voted active SONs uint64_t total_voted_time = 0; // Total Downtime barring the current down time in seconds, used for stats to present to user @@ -47,9 +47,9 @@ namespace graphene { namespace chain { // Deregistered Timestamp fc::time_point_sec deregistered_timestamp; // Total sidechain transactions reported by SON network while SON was active - uint64_t total_sidechain_txs_reported = 0; + flat_map total_sidechain_txs_reported; // Sidechain transactions reported by this SON - uint64_t sidechain_txs_reported = 0; + flat_map sidechain_txs_reported; }; /** diff --git a/libraries/chain/protocol/memo.cpp b/libraries/chain/protocol/memo.cpp index afa0b486..1602ae77 100644 --- a/libraries/chain/protocol/memo.cpp +++ b/libraries/chain/protocol/memo.cpp @@ -30,7 +30,7 @@ namespace graphene { namespace chain { void memo_data::set_message(const fc::ecc::private_key& priv, const fc::ecc::public_key& pub, const string& msg, uint64_t custom_nonce) { - if( priv != fc::ecc::private_key() && public_key_type(pub) != public_key_type() ) + if( priv != fc::ecc::private_key() && pub.valid() ) { from = priv.get_public_key(); to = pub; @@ -57,7 +57,7 @@ void memo_data::set_message(const fc::ecc::private_key& priv, const fc::ecc::pub string memo_data::get_message(const fc::ecc::private_key& priv, const fc::ecc::public_key& pub)const { - if( from != public_key_type() ) + if( from != public_key_type() && pub.valid() ) { auto secret = priv.get_shared_secret(pub); auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str()); diff --git a/libraries/chain/sidechain_address_evaluator.cpp b/libraries/chain/sidechain_address_evaluator.cpp index ae802627..625ef2f0 100644 --- a/libraries/chain/sidechain_address_evaluator.cpp +++ b/libraries/chain/sidechain_address_evaluator.cpp @@ -9,7 +9,9 @@ namespace graphene { namespace chain { void_result add_sidechain_address_evaluator::do_evaluate(const sidechain_address_add_operation& op) { try{ - FC_ASSERT( op.deposit_public_key.length() > 0 && op.deposit_address.length() == 0 && op.deposit_address_data.length() == 0, "User should add a valid deposit public key and a null deposit address"); + if (op.sidechain == sidechain_type::bitcoin) { + FC_ASSERT( op.deposit_public_key.length() > 0 && op.deposit_address.length() == 0 && op.deposit_address_data.length() == 0, "ser should add a valid deposit public key and a null deposit address (Bitcoin only)"); + } const auto& sdpke_idx = db().get_index_type().indices().get(); FC_ASSERT( sdpke_idx.find(boost::make_tuple(op.sidechain, op.deposit_public_key, time_point_sec::maximum())) == sdpke_idx.end(), "An active deposit key already exists" ); return void_result(); @@ -31,8 +33,8 @@ object_id_type add_sidechain_address_evaluator::do_apply(const sidechain_address obj.sidechain_address_account = op.sidechain_address_account; obj.sidechain = op.sidechain; obj.deposit_public_key = op.deposit_public_key; - obj.deposit_address = ""; - obj.deposit_address_data = ""; + obj.deposit_address = op.deposit_address; + obj.deposit_address_data = op.deposit_address_data; obj.withdraw_public_key = op.withdraw_public_key; obj.withdraw_address = op.withdraw_address; obj.valid_from = db().head_block_time(); diff --git a/libraries/chain/sidechain_transaction_evaluator.cpp b/libraries/chain/sidechain_transaction_evaluator.cpp index 12bf2f42..ba256199 100644 --- a/libraries/chain/sidechain_transaction_evaluator.cpp +++ b/libraries/chain/sidechain_transaction_evaluator.cpp @@ -28,6 +28,7 @@ void_result sidechain_transaction_create_evaluator::do_evaluate(const sidechain_ object_id_type sidechain_transaction_create_evaluator::do_apply(const sidechain_transaction_create_operation &op) { try { const auto &new_sidechain_transaction_object = db().create([&](sidechain_transaction_object &sto) { + sto.timestamp = db().head_block_time(); sto.sidechain = op.sidechain; sto.object_id = op.object_id; sto.transaction = op.transaction; @@ -97,7 +98,15 @@ object_id_type sidechain_transaction_sign_evaluator::do_apply(const sidechain_tr }); db().modify(son_obj->statistics(db()), [&](son_statistics_object& sso) { - sso.txs_signed += 1; + if (sso.total_txs_signed.find(sto_obj->sidechain) == sso.total_txs_signed.end()) { + sso.total_txs_signed[sto_obj->sidechain] = 0; + } + sso.total_txs_signed[sto_obj->sidechain] += 1; + + if (sso.txs_signed.find(sto_obj->sidechain) == sso.txs_signed.end()) { + sso.txs_signed[sto_obj->sidechain] = 0; + } + sso.txs_signed[sto_obj->sidechain] += 1; }); return op.sidechain_transaction_id; diff --git a/libraries/chain/son_object.cpp b/libraries/chain/son_object.cpp index bf54c833..e782a3e9 100644 --- a/libraries/chain/son_object.cpp +++ b/libraries/chain/son_object.cpp @@ -10,6 +10,8 @@ namespace graphene { namespace chain { return ((std::string(signing_key).length() > 0) && (sidechain_public_keys.size() > 0) && (sidechain_public_keys.find( sidechain_type::bitcoin ) != sidechain_public_keys.end()) && - (sidechain_public_keys.at(sidechain_type::bitcoin).length() > 0)); + (sidechain_public_keys.at(sidechain_type::bitcoin).length() > 0) && + (sidechain_public_keys.find( sidechain_type::hive ) != sidechain_public_keys.end()) && + (sidechain_public_keys.at(sidechain_type::hive).length() > 0)); } }} diff --git a/libraries/chain/son_wallet_deposit_evaluator.cpp b/libraries/chain/son_wallet_deposit_evaluator.cpp index 24a87e47..f9620282 100644 --- a/libraries/chain/son_wallet_deposit_evaluator.cpp +++ b/libraries/chain/son_wallet_deposit_evaluator.cpp @@ -84,9 +84,16 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de auto stats_itr = db().get_index_type().indices().get().find(si.son_id); db().modify(*stats_itr, [&op, &si](son_statistics_object &sso) { - sso.total_sidechain_txs_reported = sso.total_sidechain_txs_reported + 1; + if (sso.total_sidechain_txs_reported.find(op.sidechain) == sso.total_sidechain_txs_reported.end()) { + sso.total_sidechain_txs_reported[op.sidechain] = 0; + } + sso.total_sidechain_txs_reported[op.sidechain] += 1; + if (si.son_id == op.son_id) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; } }); } @@ -122,7 +129,10 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de }); auto stats_itr = db().get_index_type().indices().get().find(op.son_id); db().modify(*stats_itr, [&op](son_statistics_object &sso) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; }); return (*itr).id; } diff --git a/libraries/chain/son_wallet_withdraw_evaluator.cpp b/libraries/chain/son_wallet_withdraw_evaluator.cpp index bf6adaf9..2110e49d 100644 --- a/libraries/chain/son_wallet_withdraw_evaluator.cpp +++ b/libraries/chain/son_wallet_withdraw_evaluator.cpp @@ -82,9 +82,16 @@ object_id_type create_son_wallet_withdraw_evaluator::do_apply(const son_wallet_w auto stats_itr = db().get_index_type().indices().get().find(si.son_id); db().modify(*stats_itr, [&op, &si](son_statistics_object &sso) { - sso.total_sidechain_txs_reported = sso.total_sidechain_txs_reported + 1; + if (sso.total_sidechain_txs_reported.find(op.sidechain) == sso.total_sidechain_txs_reported.end()) { + sso.total_sidechain_txs_reported[op.sidechain] = 0; + } + sso.total_sidechain_txs_reported[op.sidechain] += 1; + if (si.son_id == op.son_id) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; } }); } @@ -120,7 +127,10 @@ object_id_type create_son_wallet_withdraw_evaluator::do_apply(const son_wallet_w }); auto stats_itr = db().get_index_type().indices().get().find(op.son_id); db().modify(*stats_itr, [&op](son_statistics_object &sso) { - sso.sidechain_txs_reported = sso.sidechain_txs_reported + 1; + if (sso.sidechain_txs_reported.find(op.sidechain) == sso.sidechain_txs_reported.end()) { + sso.sidechain_txs_reported[op.sidechain] = 0; + } + sso.sidechain_txs_reported[op.sidechain] += 1; }); return (*itr).id; } diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 3737ae61..bb74df29 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -5,6 +5,7 @@ add_library( peerplays_sidechain sidechain_net_manager.cpp sidechain_net_handler.cpp sidechain_net_handler_bitcoin.cpp + sidechain_net_handler_hive.cpp sidechain_net_handler_peerplays.cpp bitcoin/bech32.cpp bitcoin/bitcoin_address.cpp @@ -13,6 +14,12 @@ add_library( peerplays_sidechain bitcoin/segwit_addr.cpp bitcoin/utils.cpp bitcoin/sign_bitcoin_transaction.cpp + common/rpc_client.cpp + common/utils.cpp + hive/asset.cpp + hive/operations.cpp + hive/transaction.cpp + hive/types.cpp ) if (ENABLE_DEV_FEATURES) @@ -36,7 +43,7 @@ endif() unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS) unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE) -target_link_libraries( peerplays_sidechain PRIVATE graphene_plugin zmq ) +target_link_libraries( peerplays_sidechain PRIVATE curl graphene_plugin zmq ) target_include_directories( peerplays_sidechain PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp b/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp index 2e71adb5..50c02964 100644 --- a/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp +++ b/libraries/plugins/peerplays_sidechain/bitcoin/bitcoin_script.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include namespace graphene { namespace peerplays_sidechain { namespace bitcoin { diff --git a/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp new file mode 100644 index 00000000..ce4081c2 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/common/rpc_client.cpp @@ -0,0 +1,185 @@ +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace graphene { namespace peerplays_sidechain { + +rpc_client::rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : + ip(_ip), + port(_port), + user(_user), + password(_password), + debug_rpc_calls(_debug_rpc_calls), + request_id(0) { + authorization.key = "Authorization"; + authorization.val = "Basic " + fc::base64_encode(user + ":" + password); +} + +std::string rpc_client::retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx) { + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + if (json.find("result") == json.not_found()) { + return ""; + } + auto json_result = json.get_child("result"); + if (json_result.find(array_path) == json_result.not_found()) { + return ""; + } + + boost::property_tree::ptree array_ptree = json_result; + if (!array_path.empty()) { + array_ptree = json_result.get_child(array_path); + } + uint32_t array_el_idx = -1; + for (const auto &array_el : array_ptree) { + array_el_idx = array_el_idx + 1; + if (array_el_idx == idx) { + std::stringstream ss_res; + boost::property_tree::json_parser::write_json(ss_res, array_el.second); + return ss_res.str(); + } + } + + return ""; +} + +std::string rpc_client::retrieve_value_from_reply(std::string reply_str, std::string value_path) { + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + if (json.find("result") == json.not_found()) { + return ""; + } + auto json_result = json.get_child("result"); + if (json_result.find(value_path) == json_result.not_found()) { + return ""; + } + return json_result.get(value_path); +} + +std::string rpc_client::send_post_request(std::string method, std::string params, bool show_log) { + std::stringstream body; + + request_id = request_id + 1; + + body << "{ \"jsonrpc\": \"2.0\", \"id\": " << request_id << ", \"method\": \"" << method << "\""; + + if (!params.empty()) { + body << ", \"params\": " << params; + } + + body << " }"; + + const auto reply = send_post_request(body.str(), show_log); + + if (reply.body.empty()) { + wlog("RPC call ${function} failed", ("function", __FUNCTION__)); + return ""; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + return ss.str(); + } + + if (json.count("error") && !json.get_child("error").empty()) { + wlog("RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body.str())("msg", ss.str())); + } + return ""; +} + +//fc::http::reply rpc_client::send_post_request(std::string body, bool show_log) { +// fc::http::connection conn; +// conn.connect_to(fc::ip::endpoint(fc::ip::address(ip), port)); +// +// std::string url = "http://" + ip + ":" + std::to_string(port); +// +// //if (wallet.length() > 0) { +// // url = url + "/wallet/" + wallet; +// //} +// +// fc::http::reply reply = conn.request("POST", url, body, fc::http::headers{authorization}); +// +// if (show_log) { +// ilog("### Request URL: ${url}", ("url", url)); +// ilog("### Request: ${body}", ("body", body)); +// std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); +// ilog("### Response: ${ss}", ("ss", ss.str())); +// } +// +// return reply; +//} + +static size_t write_callback(char *ptr, size_t size, size_t nmemb, rpc_reply *reply) { + size_t retval = 0; + if (reply != nullptr) { + reply->body.append(ptr, size * nmemb); + retval = size * nmemb; + } + return retval; +} + +rpc_reply rpc_client::send_post_request(std::string body, bool show_log) { + + struct curl_slist *headers = nullptr; + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charset: utf-8"); + + CURL *curl = curl_easy_init(); + if (ip.find("https://", 0) != 0) { + curl_easy_setopt(curl, CURLOPT_URL, ip.c_str()); + curl_easy_setopt(curl, CURLOPT_PORT, port); + } else { + std::string full_address = ip + ":" + std::to_string(port); + curl_easy_setopt(curl, CURLOPT_URL, full_address.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); + } + if (!user.empty()) { + curl_easy_setopt(curl, CURLOPT_USERNAME, user.c_str()); + curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str()); + } + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str()); + + //curl_easy_setopt(curl, CURLOPT_VERBOSE, true); + + rpc_reply reply; + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reply); + + curl_easy_perform(curl); + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &reply.status); + + curl_easy_cleanup(curl); + curl_slist_free_all(headers); + + if (show_log) { + std::string url = ip + ":" + std::to_string(port); + ilog("### Request URL: ${url}", ("url", url)); + ilog("### Request: ${body}", ("body", body)); + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + ilog("### Response: ${ss}", ("ss", ss.str())); + } + + return reply; +} + +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/common/utils.cpp b/libraries/plugins/peerplays_sidechain/common/utils.cpp new file mode 100644 index 00000000..4491487f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/common/utils.cpp @@ -0,0 +1,8 @@ +#include + +std::string object_id_to_string(graphene::chain::object_id_type id) { + std::string object_id = fc::to_string(id.space()) + "." + + fc::to_string(id.type()) + "." + + fc::to_string(id.instance()); + return object_id; +} diff --git a/libraries/plugins/peerplays_sidechain/hive/asset.cpp b/libraries/plugins/peerplays_sidechain/hive/asset.cpp new file mode 100644 index 00000000..7417107f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/asset.cpp @@ -0,0 +1,69 @@ +#include + +#include + +#include +#include + +#define ASSET_AMOUNT_KEY "amount" +#define ASSET_PRECISION_KEY "precision" +#define ASSET_NAI_KEY "nai" + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +uint64_t asset::hbd_symbol_ser = HBD_SYMBOL_SER; +uint64_t asset::hive_symbol_ser = HIVE_SYMBOL_SER; + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth) { + try { + if (var.symbol == HBD_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(HBD_PRECISION))(ASSET_NAI_KEY, HBD_NAI); + vo = v; + } + if (var.symbol == HIVE_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(HIVE_PRECISION))(ASSET_NAI_KEY, HIVE_NAI); + vo = v; + } + if (var.symbol == TBD_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(TBD_PRECISION))(ASSET_NAI_KEY, TBD_NAI); + vo = v; + } + if (var.symbol == TESTS_SYMBOL_SER) { + variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(TESTS_PRECISION))(ASSET_NAI_KEY, TESTS_NAI); + vo = v; + } + } + FC_CAPTURE_AND_RETHROW() +} + +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset &vo, uint32_t max_depth) { + try { + FC_ASSERT(var.is_object(), "Asset has to be treated as object."); + + const auto &v_object = var.get_object(); + + FC_ASSERT(v_object.contains(ASSET_AMOUNT_KEY), "Amount field doesn't exist."); + FC_ASSERT(v_object[ASSET_AMOUNT_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_AMOUNT_KEY)); + vo.amount = boost::lexical_cast(v_object[ASSET_AMOUNT_KEY].as(max_depth)); + FC_ASSERT(vo.amount >= 0, "Asset amount cannot be negative"); + + FC_ASSERT(v_object.contains(ASSET_PRECISION_KEY), "Precision field doesn't exist."); + FC_ASSERT(v_object[ASSET_PRECISION_KEY].is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_PRECISION_KEY)); + + FC_ASSERT(v_object.contains(ASSET_NAI_KEY), "NAI field doesn't exist."); + FC_ASSERT(v_object[ASSET_NAI_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_NAI_KEY)); + + if (v_object[ASSET_NAI_KEY].as(max_depth) == HBD_NAI) { + vo.symbol = graphene::peerplays_sidechain::hive::asset::hbd_symbol_ser; + } + if (v_object[ASSET_NAI_KEY].as(max_depth) == HIVE_NAI) { + vo.symbol = graphene::peerplays_sidechain::hive::asset::hive_symbol_ser; + } + } + FC_CAPTURE_AND_RETHROW() +} +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/hive/operations.cpp b/libraries/plugins/peerplays_sidechain/hive/operations.cpp new file mode 100644 index 00000000..b21b564e --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/operations.cpp @@ -0,0 +1,101 @@ +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +static std::string trim_typename_namespace(const std::string &name) { + auto start = name.find_last_of(':'); + start = (start == std::string::npos) ? 0 : start + 1; + return name.substr(start); +} + +struct from_static_variant_for_hive { + fc::variant &var; + from_static_variant_for_hive(fc::variant &dv) : + var(dv) { + } + + typedef void result_type; + template + void operator()(const T &v) const { + auto name = trim_typename_namespace(fc::get_typename::name()); + fc::variant value; + to_variant(v, value, 5); + var = mutable_variant_object("type", name).set("value", value); + } +}; + +struct to_static_variant_for_hive { + const fc::variant &var; + to_static_variant_for_hive(const fc::variant &dv) : + var(dv) { + } + + typedef void result_type; + template + void operator()(T &v) const { + from_variant(var, v, 5); + } +}; + +struct get_static_variant_name { + string &name; + get_static_variant_name(string &n) : + name(n) { + } + + typedef void result_type; + template + void operator()(T &v) const { + name = trim_typename_namespace(fc::get_typename::name()); + } +}; + +void to_variant(const graphene::peerplays_sidechain::hive::hive_operation &var, fc::variant &vo, uint32_t max_depth) { + var.visit(from_static_variant_for_hive(vo)); +} + +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::hive_operation &vo, uint32_t max_depth) { + static std::map to_tag = []() { + std::map name_map; + for (int i = 0; i < graphene::peerplays_sidechain::hive::hive_operation::count(); ++i) { + graphene::peerplays_sidechain::hive::hive_operation tmp; + tmp.set_which(i); + string n; + tmp.visit(get_static_variant_name(n)); + name_map[n] = i; + } + return name_map; + }(); + + auto ar = var.get_array(); + if (ar.size() < 2) + return; + auto var_second = ar[1]; + + FC_ASSERT(var_second.is_object(), "Input data have to treated as object."); + auto v_object = var_second.get_object(); + + FC_ASSERT(v_object.contains("type"), "Type field doesn't exist."); + FC_ASSERT(v_object.contains("value"), "Value field doesn't exist."); + + int64_t which = -1; + + if (v_object["type"].is_integer()) { + which = v_object["type"].as_int64(); + } else { + auto itr = to_tag.find(v_object["type"].as_string()); + FC_ASSERT(itr != to_tag.end(), "Invalid object name: ${n}", ("n", v_object["type"])); + which = itr->second; + } + + vo.set_which(which); + vo.visit(fc::to_static_variant_for_hive(v_object["value"])); +} + +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/hive/transaction.cpp b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp new file mode 100644 index 00000000..3e4a59f5 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/transaction.cpp @@ -0,0 +1,57 @@ +#include + +#include + +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +digest_type transaction::digest() const { + digest_type::encoder enc; + fc::raw::pack(enc, *this); + return enc.result(); +} + +transaction_id_type transaction::id() const { + auto h = digest(); + transaction_id_type result; + memcpy(result._hash, h._hash, std::min(sizeof(result), sizeof(h))); + return result; +} + +digest_type transaction::sig_digest(const chain_id_type &chain_id) const { + digest_type::encoder enc; + fc::raw::pack(enc, chain_id); + fc::raw::pack(enc, *this); + return enc.result(); +} + +void transaction::set_expiration(fc::time_point_sec expiration_time) { + expiration = expiration_time; +} + +void transaction::set_reference_block(const block_id_type &reference_block) { + ref_block_num = fc::endian_reverse_u32(reference_block._hash[0]); + ref_block_prefix = reference_block._hash[1]; +} + +void signed_transaction::clear() { + operations.clear(); + signatures.clear(); +} + +const signature_type &signed_transaction::sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) { + digest_type h = sig_digest(chain_id); + signatures.push_back(key.sign_compact(h, true)); + return signatures.back(); +} + +signature_type signed_transaction::sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) const { + digest_type::encoder enc; + fc::raw::pack(enc, chain_id); + fc::raw::pack(enc, *this); + return key.sign_compact(enc.result(), true); +} + +}}} // namespace graphene::peerplays_sidechain::hive diff --git a/libraries/plugins/peerplays_sidechain/hive/types.cpp b/libraries/plugins/peerplays_sidechain/hive/types.cpp new file mode 100644 index 00000000..7a5506e7 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/hive/types.cpp @@ -0,0 +1,73 @@ +#include + +#include +#include +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +std::string public_key_type::prefix = KEY_PREFIX_STM; + +public_key_type::public_key_type() : + key_data(){}; + +public_key_type::public_key_type(const fc::ecc::public_key_data &data) : + key_data(data){}; + +public_key_type::public_key_type(const fc::ecc::public_key &pubkey) : + key_data(pubkey){}; + +public_key_type::public_key_type(const std::string &base58str) { + const size_t prefix_len = prefix.size(); + FC_ASSERT(base58str.size() > prefix_len); + FC_ASSERT(base58str.substr(0, prefix_len) == prefix, "", ("base58str", base58str)); + auto bin = fc::from_base58(base58str.substr(prefix_len)); + auto bin_key = fc::raw::unpack(bin); + key_data = bin_key.data; + FC_ASSERT(fc::ripemd160::hash(key_data.data, key_data.size())._hash[0] == bin_key.check); +}; + +public_key_type::operator fc::ecc::public_key_data() const { + return key_data; +}; + +public_key_type::operator fc::ecc::public_key() const { + return fc::ecc::public_key(key_data); +}; + +public_key_type::operator std::string() const { + binary_key k; + k.data = key_data; + k.check = fc::ripemd160::hash(k.data.data, k.data.size())._hash[0]; + auto data = fc::raw::pack(k); + return prefix + fc::to_base58(data.data(), data.size()); +} + +bool operator==(const public_key_type &p1, const fc::ecc::public_key &p2) { + return p1.key_data == p2.serialize(); +} + +bool operator==(const public_key_type &p1, const public_key_type &p2) { + return p1.key_data == p2.key_data; +} + +bool operator!=(const public_key_type &p1, const public_key_type &p2) { + return p1.key_data != p2.key_data; +} + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +using namespace std; + +void to_variant(const graphene::peerplays_sidechain::hive::public_key_type &var, fc::variant &vo, uint32_t max_depth) { + vo = std::string(var); +} + +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::public_key_type &vo, uint32_t max_depth) { + vo = graphene::peerplays_sidechain::hive::public_key_type(var.as_string()); +} + +} // namespace fc diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp new file mode 100644 index 00000000..f61bdb3f --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/rpc_client.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include + +namespace graphene { namespace peerplays_sidechain { + +struct rpc_reply { + uint16_t status; + std::string body; +}; + +class rpc_client { +public: + rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls); + +protected: + std::string retrieve_array_value_from_reply(std::string reply_str, std::string array_path, uint32_t idx); + std::string retrieve_value_from_reply(std::string reply_str, std::string value_path); + std::string send_post_request(std::string method, std::string params, bool show_log); + + std::string ip; + uint32_t port; + std::string user; + std::string password; + bool debug_rpc_calls; + + uint32_t request_id; + + fc::http::header authorization; + +private: + //fc::http::reply send_post_request(std::string body, bool show_log); + rpc_reply send_post_request(std::string body, bool show_log); +}; + +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp new file mode 100644 index 00000000..99c59019 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/common/utils.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include + +std::string object_id_to_string(graphene::chain::object_id_type id); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp new file mode 100644 index 00000000..f0743741 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/asset.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +#define HBD_NAI "@@000000013" +#define HBD_PRECISION 3 +#define HBD_SYMBOL_U64 (uint64_t('S') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define HBD_SYMBOL_SER (uint64_t(3) | (HBD_SYMBOL_U64 << 8)) + +#define HIVE_NAI "@@000000021" +#define HIVE_PRECISION 3 +#define HIVE_SYMBOL_U64 (uint64_t('S') | (uint64_t('T') << 8) | (uint64_t('E') << 16) | (uint64_t('E') << 24) | (uint64_t('M') << 32)) +#define HIVE_SYMBOL_SER (uint64_t(3) | (HIVE_SYMBOL_U64 << 8)) + +#define TBD_NAI "@@000000013" +#define TBD_PRECISION 3 +#define TBD_SYMBOL_U64 (uint64_t('T') | (uint64_t('B') << 8) | (uint64_t('D') << 16)) +#define TBD_SYMBOL_SER (uint64_t(3) | (TBD_SYMBOL_U64 << 8)) + +#define TESTS_NAI "@@000000021" +#define TESTS_PRECISION 3 +#define TESTS_SYMBOL_U64 (uint64_t('T') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32)) +#define TESTS_SYMBOL_SER (uint64_t(3) | (TESTS_SYMBOL_U64 << 8)) + +struct asset { + static uint64_t hbd_symbol_ser; + static uint64_t hive_symbol_ser; + share_type amount; + uint64_t symbol; +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { +void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth); +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset &vo, uint32_t max_depth); +} // namespace fc + +FC_REFLECT(graphene::peerplays_sidechain::hive::asset, (amount)(symbol)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp new file mode 100644 index 00000000..bd67ae23 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/authority.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct authority { + authority() { + } + + enum classification { + owner = 0, + active = 1, + key = 2, + posting = 3 + }; + + uint32_t weight_threshold = 0; + fc::flat_map account_auths; + fc::flat_map key_auths; +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT_ENUM(graphene::peerplays_sidechain::hive::authority::classification, + (owner)(active)(key)(posting)) + +FC_REFLECT(graphene::peerplays_sidechain::hive::authority, + (weight_threshold)(account_auths)(key_auths)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp new file mode 100644 index 00000000..1348ce35 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/hive_operations.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include +#include + +#include + +#include +#include +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct vote_operation {}; +struct comment_operation {}; + +struct transfer_operation { + hive::account_name_type from; + hive::account_name_type to; + hive::asset amount; + std::string memo; +}; + +struct transfer_to_vesting_operation {}; +struct withdraw_vesting_operation {}; +struct limit_order_create_operation {}; +struct limit_order_cancel_operation {}; +struct feed_publish_operation {}; +struct convert_operation {}; +struct account_create_operation {}; + +struct account_update_operation { + hive::account_name_type account; + fc::optional owner; + fc::optional active; + fc::optional posting; + hive::public_key_type memo_key; + std::string json_metadata; +}; + +struct witness_update_operation {}; +struct account_witness_vote_operation {}; +struct account_witness_proxy_operation {}; +struct pow_operation {}; +struct custom_operation {}; +struct report_over_production_operation {}; +struct delete_comment_operation {}; +struct custom_json_operation {}; +struct comment_options_operation {}; +struct set_withdraw_vesting_route_operation {}; +struct limit_order_create2_operation {}; +struct claim_account_operation {}; +struct create_claimed_account_operation {}; +struct request_account_recovery_operation {}; +struct recover_account_operation {}; +struct change_recovery_account_operation {}; +struct escrow_transfer_operation {}; +struct escrow_dispute_operation {}; +struct escrow_release_operation {}; +struct pow2_operation {}; +struct escrow_approve_operation {}; +struct transfer_to_savings_operation {}; +struct transfer_from_savings_operation {}; +struct cancel_transfer_from_savings_operation {}; +struct custom_binary_operation {}; +struct decline_voting_rights_operation {}; +struct reset_account_operation {}; +struct set_reset_account_operation {}; +struct claim_reward_balance_operation {}; + +struct delegate_vesting_shares_operation { + hive::account_name_type delegator; + hive::account_name_type delegatee; + hive::asset vesting_shares; +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT(graphene::peerplays_sidechain::hive::vote_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::comment_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_operation, + (from)(to)(amount)(memo)) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_vesting_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::withdraw_vesting_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_cancel_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::feed_publish_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::convert_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_create_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_update_operation, + (account)(owner)(active)(posting)(memo_key)(json_metadata)) +FC_REFLECT(graphene::peerplays_sidechain::hive::witness_update_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_witness_vote_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::account_witness_proxy_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::pow_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::custom_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::report_over_production_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::delete_comment_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::custom_json_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::comment_options_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::set_withdraw_vesting_route_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create2_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::claim_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::create_claimed_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::request_account_recovery_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::recover_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::change_recovery_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_transfer_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_dispute_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_release_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::pow2_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::escrow_approve_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_savings_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_from_savings_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::cancel_transfer_from_savings_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::custom_binary_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::decline_voting_rights_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::reset_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::set_reset_account_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::claim_reward_balance_operation, ) +FC_REFLECT(graphene::peerplays_sidechain::hive::delegate_vesting_shares_operation, + (delegator)(delegatee)(vesting_shares)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp new file mode 100644 index 00000000..e64eb1ae --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/operations.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +typedef fc::static_variant< + vote_operation, + comment_operation, + + transfer_operation, + transfer_to_vesting_operation, + withdraw_vesting_operation, + + limit_order_create_operation, + limit_order_cancel_operation, + + feed_publish_operation, + convert_operation, + + account_create_operation, + account_update_operation, + + witness_update_operation, + account_witness_vote_operation, + account_witness_proxy_operation, + + pow_operation, + + custom_operation, + + report_over_production_operation, + + delete_comment_operation, + custom_json_operation, + comment_options_operation, + set_withdraw_vesting_route_operation, + limit_order_create2_operation, + claim_account_operation, + create_claimed_account_operation, + request_account_recovery_operation, + recover_account_operation, + change_recovery_account_operation, + escrow_transfer_operation, + escrow_dispute_operation, + escrow_release_operation, + pow2_operation, + escrow_approve_operation, + transfer_to_savings_operation, + transfer_from_savings_operation, + cancel_transfer_from_savings_operation, + custom_binary_operation, + decline_voting_rights_operation, + reset_account_operation, + set_reset_account_operation, + claim_reward_balance_operation, + delegate_vesting_shares_operation> + hive_operation; + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { + +void to_variant(const graphene::peerplays_sidechain::hive::hive_operation &var, fc::variant &vo, uint32_t max_depth = 5); +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::hive_operation &vo, uint32_t max_depth = 5); + +} // namespace fc + +FC_REFLECT_TYPENAME(graphene::peerplays_sidechain::hive::hive_operation) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp new file mode 100644 index 00000000..8b35b7b3 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/transaction.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +struct transaction { + uint16_t ref_block_num = 0; + uint32_t ref_block_prefix = 0; + fc::time_point_sec expiration; + std::vector operations; + extensions_type extensions; + + digest_type digest() const; + transaction_id_type id() const; + digest_type sig_digest(const chain_id_type &chain_id) const; + + void set_expiration(fc::time_point_sec expiration_time); + void set_reference_block(const block_id_type &reference_block); +}; + +struct signed_transaction : public transaction { + + std::vector signatures; + + const signature_type &sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id); + signature_type sign(const hive::private_key_type &key, const hive::chain_id_type &chain_id) const; + void clear(); +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +FC_REFLECT(graphene::peerplays_sidechain::hive::transaction, + (ref_block_num)(ref_block_prefix)(expiration)(operations)(extensions)) + +FC_REFLECT_DERIVED(graphene::peerplays_sidechain::hive::signed_transaction, + (graphene::peerplays_sidechain::hive::transaction), + (signatures)) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp new file mode 100644 index 00000000..f5b986e4 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/hive/types.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include + +namespace graphene { namespace peerplays_sidechain { namespace hive { + +#define KEY_PREFIX_STM "STM" +#define KEY_PREFIX_TST "TST" + +enum network { + mainnet, + testnet +}; + +struct void_t {}; + +typedef fc::static_variant future_extensions; +typedef fc::flat_set extensions_type; + +typedef fc::ecc::private_key private_key_type; +typedef fc::sha256 chain_id_type; +typedef std::string account_name_type; +typedef fc::ripemd160 block_id_type; +//typedef fc::ripemd160 checksum_type; +typedef fc::ripemd160 transaction_id_type; +typedef fc::sha256 digest_type; +typedef fc::ecc::compact_signature signature_type; +typedef fc::safe share_type; +//typedef safe ushare_type; +//typedef uint16_t weight_type; +//typedef uint32_t contribution_id_type; +//typedef fixed_string<32> custom_id_type; + +struct public_key_type { + + static std::string prefix; + + struct binary_key { + binary_key() { + } + uint32_t check = 0; + fc::ecc::public_key_data data; + }; + fc::ecc::public_key_data key_data; + public_key_type(); + public_key_type(const fc::ecc::public_key_data &data); + public_key_type(const fc::ecc::public_key &pubkey); + explicit public_key_type(const std::string &base58str); + operator fc::ecc::public_key_data() const; + operator fc::ecc::public_key() const; + explicit operator std::string() const; + friend bool operator==(const public_key_type &p1, const fc::ecc::public_key &p2); + friend bool operator==(const public_key_type &p1, const public_key_type &p2); + friend bool operator<(const public_key_type &p1, const public_key_type &p2) { + return p1.key_data < p2.key_data; + } + friend bool operator!=(const public_key_type &p1, const public_key_type &p2); +}; + +}}} // namespace graphene::peerplays_sidechain::hive + +namespace fc { +void to_variant(const graphene::peerplays_sidechain::hive::public_key_type &var, fc::variant &vo, uint32_t max_depth = 2); +void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::public_key_type &vo, uint32_t max_depth = 2); +} // namespace fc + +FC_REFLECT(graphene::peerplays_sidechain::hive::public_key_type, (key_data)) +FC_REFLECT(graphene::peerplays_sidechain::hive::public_key_type::binary_key, (data)(check)) + +FC_REFLECT(graphene::peerplays_sidechain::hive::void_t, ) +FC_REFLECT_TYPENAME(graphene::peerplays_sidechain::hive::future_extensions) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp index 5b7ea6e9..6adfe944 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp @@ -37,6 +37,7 @@ public: boost::program_options::options_description &cfg) override; virtual void plugin_initialize(const boost::program_options::variables_map &options) override; virtual void plugin_startup() override; + virtual void plugin_shutdown() override; std::unique_ptr my; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 50dfd505..21526d05 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -4,7 +4,6 @@ #include -#include #include #include #include @@ -46,15 +45,19 @@ public: virtual bool process_withdrawal(const son_wallet_withdraw_object &swwo) = 0; virtual std::string process_sidechain_transaction(const sidechain_transaction_object &sto) = 0; virtual std::string send_sidechain_transaction(const sidechain_transaction_object &sto) = 0; - virtual int64_t settle_sidechain_transaction(const sidechain_transaction_object &sto) = 0; + virtual bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) = 0; protected: peerplays_sidechain_plugin &plugin; graphene::chain::database &database; sidechain_type sidechain; + bool debug_rpc_calls; + std::map private_keys; + void on_applied_block(const signed_block &b); + private: }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index eb218a4c..dd6ebb28 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -1,13 +1,14 @@ #pragma once -#include #include #include #include +#include + #include -#include +#include namespace graphene { namespace peerplays_sidechain { @@ -20,7 +21,7 @@ public: class bitcoin_rpc_client { public: - bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password); + bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password, bool _debug_rpc_calls); std::string addmultisigaddress(const uint32_t nrequired, const std::vector public_keys); std::string combinepsbt(const vector &psbts); @@ -50,7 +51,7 @@ public: //bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60); private: - fc::http::reply send_post_request(std::string body, bool show_log = false); + fc::http::reply send_post_request(std::string body, bool show_log); std::string ip; uint32_t rpc_port; @@ -58,6 +59,7 @@ private: std::string password; std::string wallet; std::string wallet_password; + bool debug_rpc_calls; fc::http::header authorization; }; @@ -68,7 +70,7 @@ class zmq_listener { public: zmq_listener(std::string _ip, uint32_t _zmq); - fc::signal event_received; + boost::signals2::signal event_received; private: void handle_zmq(); @@ -95,7 +97,7 @@ public: bool process_withdrawal(const son_wallet_withdraw_object &swwo); std::string process_sidechain_transaction(const sidechain_transaction_object &sto); std::string send_sidechain_transaction(const sidechain_transaction_object &sto); - int64_t settle_sidechain_transaction(const sidechain_transaction_object &sto); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); private: std::string ip; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp new file mode 100644 index 00000000..675c3cdd --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include + +#include + +#include + +#include +#include +#include + +namespace graphene { namespace peerplays_sidechain { + +class hive_node_rpc_client : public rpc_client { +public: + hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls); + + std::string account_history_api_get_transaction(std::string transaction_id); + std::string block_api_get_block(uint32_t block_number); + std::string condenser_api_get_accounts(std::vector accounts); + std::string condenser_api_get_config(); + std::string database_api_get_dynamic_global_properties(); + std::string database_api_get_version(); + std::string network_broadcast_api_broadcast_transaction(std::string htrx); + + std::string get_account(std::string account); + std::string get_account_memo_key(std::string account); + std::string get_chain_id(); + std::string get_head_block_id(); + std::string get_head_block_time(); + std::string get_is_test_net(); + std::string get_last_irreversible_block_num(); +}; + +class sidechain_net_handler_hive : public sidechain_net_handler { +public: + sidechain_net_handler_hive(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options); + virtual ~sidechain_net_handler_hive(); + + bool process_proposal(const proposal_object &po); + void process_primary_wallet(); + void process_sidechain_addresses(); + bool process_deposit(const son_wallet_deposit_object &swdo); + bool process_withdrawal(const son_wallet_withdraw_object &swwo); + std::string process_sidechain_transaction(const sidechain_transaction_object &sto); + std::string send_sidechain_transaction(const sidechain_transaction_object &sto); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); + +private: + std::string node_ip; + uint32_t node_rpc_port; + std::string node_rpc_user; + std::string node_rpc_password; + hive_node_rpc_client *node_rpc_client; + + hive::chain_id_type chain_id; + hive::network network_type; + + uint64_t last_block_received; + fc::future _listener_task; + boost::signals2::signal event_received; + void schedule_hive_listener(); + void hive_listener_loop(); + void handle_event(const std::string &event_data); +}; + +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp index aa094d95..69eea1a9 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp @@ -4,8 +4,6 @@ #include -#include - namespace graphene { namespace peerplays_sidechain { class sidechain_net_handler_peerplays : public sidechain_net_handler { @@ -20,10 +18,9 @@ public: bool process_withdrawal(const son_wallet_withdraw_object &swwo); std::string process_sidechain_transaction(const sidechain_transaction_object &sto); std::string send_sidechain_transaction(const sidechain_transaction_object &sto); - int64_t settle_sidechain_transaction(const sidechain_transaction_object &sto); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); private: - void on_applied_block(const signed_block &b); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp index c2d40e14..a35c1933 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp @@ -29,6 +29,8 @@ private: peerplays_sidechain_plugin &plugin; graphene::chain::database &database; std::vector> net_handlers; + + void on_applied_block(const signed_block &b); }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index e93dd788..02a046fc 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -29,6 +29,7 @@ public: boost::program_options::options_description &cfg); void plugin_initialize(const boost::program_options::variables_map &opt); void plugin_startup(); + void plugin_shutdown(); std::set &get_sons(); const son_id_type get_current_son_id(); @@ -68,8 +69,15 @@ private: bool config_ready_son; bool config_ready_bitcoin; + bool config_ready_ethereum; + bool config_ready_hive; bool config_ready_peerplays; + bool sidechain_enabled_bitcoin; + bool sidechain_enabled_ethereum; + bool sidechain_enabled_hive; + bool sidechain_enabled_peerplays; + son_id_type current_son_id; std::unique_ptr net_manager; @@ -88,7 +96,13 @@ peerplays_sidechain_plugin_impl::peerplays_sidechain_plugin_impl(peerplays_sidec plugin(_plugin), config_ready_son(false), config_ready_bitcoin(false), + config_ready_ethereum(false), + config_ready_hive(false), config_ready_peerplays(false), + sidechain_enabled_bitcoin(false), + sidechain_enabled_ethereum(false), + sidechain_enabled_hive(false), + sidechain_enabled_peerplays(false), current_son_id(son_id_type(std::numeric_limits().max())), net_manager(nullptr), first_block_skipped(false) { @@ -125,6 +139,12 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options( cli.add_options()("son-ids", bpo::value(), ("IDs of multiple SONs controlled by this node (e.g. [" + son_id_example + ", " + son_id_example2 + "], quotes are required)").c_str()); cli.add_options()("peerplays-private-key", bpo::value>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))), "Tuple of [PublicKey, WIF private key] (may specify multiple times)"); + + cli.add_options()("sidechain-retry-threshold", bpo::value()->default_value(150), "Sidechain retry throttling threshold"); + + cli.add_options()("debug-rpc-calls", bpo::value()->default_value(false), "Outputs RPC calls to console"); + + cli.add_options()("bitcoin-sidechain-enabled", bpo::value()->default_value(false), "Bitcoin sidechain handler enabled"); cli.add_options()("bitcoin-node-ip", bpo::value()->default_value("127.0.0.1"), "IP address of Bitcoin node"); cli.add_options()("bitcoin-node-zmq-port", bpo::value()->default_value(11111), "ZMQ port of Bitcoin node"); cli.add_options()("bitcoin-node-rpc-port", bpo::value()->default_value(8332), "RPC port of Bitcoin node"); @@ -134,7 +154,15 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options( cli.add_options()("bitcoin-wallet-password", bpo::value(), "Bitcoin wallet password"); cli.add_options()("bitcoin-private-key", bpo::value>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("02d0f137e717fb3aab7aff99904001d49a0a636c5e1342f8927a4ba2eaee8e9772", "cVN31uC9sTEr392DLVUEjrtMgLA8Yb3fpYmTRj7bomTm6nn2ANPr")), "Tuple of [Bitcoin public key, Bitcoin private key] (may specify multiple times)"); - cli.add_options()("sidechain-retry-threshold", bpo::value()->default_value(150), "Sidechain retry throttling threshold"); + + cli.add_options()("hive-sidechain-enabled", bpo::value()->default_value(false), "Hive sidechain handler enabled"); + cli.add_options()("hive-node-ip", bpo::value()->default_value("127.0.0.1"), "Hive node IP address"); + cli.add_options()("hive-node-rpc-port", bpo::value()->default_value(28090), "Hive node RPC port"); + cli.add_options()("hive-node-rpc-user", bpo::value(), "Hive node RPC user"); + cli.add_options()("hive-node-rpc-password", bpo::value(), "Hive node RPC password"); + cli.add_options()("hive-private-key", bpo::value>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4", "5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n")), + "Tuple of [Hive public key, Hive private key] (may specify multiple times)"); + cfg.add(cli); } @@ -174,7 +202,9 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt } config_ready_son = config_ready_son && !private_keys.empty(); } - retries_threshold = options.at("sidechain-retry-threshold").as(); + if (options.count("sidechain-retry-threshold")) { + retries_threshold = options.at("sidechain-retry-threshold").as(); + } ilog("sidechain-retry-threshold: ${sidechain-retry-threshold}", ("sidechain-retry-threshold", retries_threshold)); } if (!config_ready_son) { @@ -182,27 +212,47 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt throw; } + sidechain_enabled_bitcoin = options.at("bitcoin-sidechain-enabled").as(); config_ready_bitcoin = options.count("bitcoin-node-ip") && options.count("bitcoin-node-zmq-port") && options.count("bitcoin-node-rpc-port") && options.count("bitcoin-node-rpc-user") && options.count("bitcoin-node-rpc-password") && - /*options.count( "bitcoin-wallet" ) && options.count( "bitcoin-wallet-password" ) &&*/ + /*options.count("bitcoin-wallet") && options.count("bitcoin-wallet-password") &&*/ options.count("bitcoin-private-key"); if (!config_ready_bitcoin) { wlog("Haven't set up Bitcoin sidechain parameters"); } - //config_ready_ethereum = options.count( "ethereum-node-ip" ) && - // options.count( "ethereum-address" ) && options.count( "ethereum-public-key" ) && options.count( "ethereum-private-key" ); + //sidechain_enabled_ethereum = options.at("ethereum-sidechain-enabled").as(); + //config_ready_ethereum = options.count("ethereum-node-ip") && + // options.count("ethereum-address") && + // options.count("ethereum-public-key") && options.count("ethereum-private-key"); //if (!config_ready_ethereum) { // wlog("Haven't set up Ethereum sidechain parameters"); //} + sidechain_enabled_hive = options.at("hive-sidechain-enabled").as(); + config_ready_hive = options.count("hive-node-ip") && + options.count("hive-node-rpc-port") && + /*options.count("hive-node-rpc-user") && options.count("hive-node-rpc-password") &&*/ + options.count("hive-private-key"); + if (!config_ready_hive) { + wlog("Haven't set up Hive sidechain parameters"); + } + +#ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS + sidechain_enabled_peerplays = true; //options.at("peerplays-sidechain-enabled").as(); +#else + sidechain_enabled_peerplays = false; +#endif config_ready_peerplays = true; if (!config_ready_peerplays) { wlog("Haven't set up Peerplays sidechain parameters"); } - if (!(config_ready_bitcoin /*&& config_ready_ethereum*/ && config_ready_peerplays)) { + if (!(config_ready_bitcoin && + /*config_ready_ethereum &&*/ + config_ready_hive && + config_ready_peerplays)) { wlog("Haven't set up any sidechain parameters"); throw; } @@ -220,17 +270,22 @@ void peerplays_sidechain_plugin_impl::plugin_startup() { net_manager = std::unique_ptr(new sidechain_net_manager(plugin)); - if (config_ready_bitcoin) { + if (sidechain_enabled_bitcoin && config_ready_bitcoin) { net_manager->create_handler(sidechain_type::bitcoin, options); ilog("Bitcoin sidechain handler running"); } - //if (config_ready_ethereum) { + //if (sidechain_enabled_ethereum && config_ready_ethereum) { // net_manager->create_handler(sidechain_type::ethereum, options); // ilog("Ethereum sidechain handler running"); //} - if (config_ready_peerplays) { + if (sidechain_enabled_hive && config_ready_hive) { + net_manager->create_handler(sidechain_type::hive, options); + ilog("Hive sidechain handler running"); + } + + if (sidechain_enabled_peerplays && config_ready_peerplays) { net_manager->create_handler(sidechain_type::peerplays, options); ilog("Peerplays sidechain handler running"); } @@ -240,6 +295,9 @@ void peerplays_sidechain_plugin_impl::plugin_startup() { }); } +void peerplays_sidechain_plugin_impl::plugin_shutdown() { +} + std::set &peerplays_sidechain_plugin_impl::get_sons() { return sons; } @@ -390,9 +448,15 @@ void peerplays_sidechain_plugin_impl::son_processing() { return; } + //fc::time_point now_fine = fc::time_point::now(); + //fc::time_point_sec now = now_fine + fc::microseconds(500000); + //if (plugin.database().get_slot_time(1) < now) { + // return; // Not synced + //} + fc::time_point now_fine = fc::time_point::now(); - fc::time_point_sec now = now_fine + fc::microseconds(500000); - if (plugin.database().get_slot_time(1) < now) { + fc::time_point_sec now = now_fine - fc::milliseconds(3000); + if (plugin.database().head_block_time() < now) { return; // Not synced } @@ -686,6 +750,12 @@ void peerplays_sidechain_plugin::plugin_startup() { ilog("peerplays sidechain plugin: plugin_startup() end"); } +void peerplays_sidechain_plugin::plugin_shutdown() { + ilog("peerplays sidechain plugin: plugin_shutdown() begin"); + my->plugin_shutdown(); + ilog("peerplays sidechain plugin: plugin_shutdown() end"); +} + std::set &peerplays_sidechain_plugin::get_sons() { return my->get_sons(); } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index d025c178..06a76502 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -1,14 +1,21 @@ #include +#include + #include #include #include +#include namespace graphene { namespace peerplays_sidechain { sidechain_net_handler::sidechain_net_handler(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : plugin(_plugin), database(_plugin.database()) { + + database.applied_block.connect([&](const signed_block &b) { + on_applied_block(b); + }); } sidechain_net_handler::~sidechain_net_handler() { @@ -161,21 +168,25 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ const chain::global_property_object &gpo = database.get_global_properties(); - asset_id_type btc_asset_id = database.get_global_properties().parameters.btc_asset(); - std::string btc_asset_id_str = fc::to_string(btc_asset_id.space_id) + "." + - fc::to_string(btc_asset_id.type_id) + "." + - fc::to_string((uint64_t)btc_asset_id.instance); - + bool enable_peerplays_asset_deposits = false; #ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS - // Accepts BTC and peerplays asset deposits - bool deposit_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) != 0)); - bool withdraw_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) == 0)); -#else - // Accepts BTC deposits only - bool deposit_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare("BTC") == 0)); - bool withdraw_condition = ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) == 0)); + //enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) && + // (sed.sidechain_currency.compare("BTC") != 0) && + // (sed.sidechain_currency.compare("HBD") != 0) && + // (sed.sidechain_currency.compare("HIVE") != 0); #endif + bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) && + (((sed.sidechain == sidechain_type::bitcoin) && (sed.sidechain_currency.compare("BTC") == 0)) || + ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HBD") == 0)) || + ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) || + enable_peerplays_asset_deposits); + + bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) && + ((sed.sidechain_currency == object_id_to_string(gpo.parameters.btc_asset())) || + (sed.sidechain_currency == object_id_to_string(gpo.parameters.hbd_asset())) || + (sed.sidechain_currency == object_id_to_string(gpo.parameters.hive_asset()))); + // Deposit request if (deposit_condition) { @@ -214,11 +225,32 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ // Withdrawal request if (withdraw_condition) { - // BTC Payout only (for now) + std::string withdraw_address = ""; const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain_type::bitcoin, time_point_sec::maximum())); - if (addr_itr == sidechain_addresses_idx.end()) + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain, time_point_sec::maximum())); + if (addr_itr != sidechain_addresses_idx.end()) { + withdraw_address = addr_itr->withdraw_address; + } else { + withdraw_address = sed.sidechain_from; + } + + std::string withdraw_currency = ""; + price withdraw_currency_price = {}; + if (sed.sidechain_currency == object_id_to_string(gpo.parameters.btc_asset())) { + withdraw_currency = "BTC"; + withdraw_currency_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + } + if (sed.sidechain_currency == object_id_to_string(gpo.parameters.hbd_asset())) { + withdraw_currency = "HBD"; + withdraw_currency_price = database.get(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate; + } + if (sed.sidechain_currency == object_id_to_string(gpo.parameters.hive_asset())) { + withdraw_currency = "HIVE"; + withdraw_currency_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; + } + if (withdraw_currency.empty()) { return; + } for (son_id_type son_id : plugin.get_sons()) { if (plugin.is_active_son(son_id)) { @@ -233,12 +265,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ op.peerplays_transaction_id = sed.sidechain_transaction_id; op.peerplays_from = sed.peerplays_from; op.peerplays_asset = sed.peerplays_asset; - // BTC payout only (for now) - op.withdraw_sidechain = sidechain_type::bitcoin; - op.withdraw_address = addr_itr->withdraw_address; - op.withdraw_currency = "BTC"; - price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; - op.withdraw_amount = sed.peerplays_asset.amount * btc_price.quote.amount / btc_price.base.amount; + op.withdraw_sidechain = sidechain; + op.withdraw_address = withdraw_address; + op.withdraw_currency = withdraw_currency; + op.withdraw_amount = sed.peerplays_asset.amount * withdraw_currency_price.quote.amount / withdraw_currency_price.base.amount; signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), op); try { @@ -389,9 +419,13 @@ void sidechain_net_handler::process_deposits() { } //Ignore the deposits which are not valid anymore, considered refunds. const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); - const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_to, time_point_sec::maximum())); + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, swdo.sidechain_from, time_point_sec::maximum())); if (addr_itr == sidechain_addresses_idx.end()) { - return; + const auto &account_idx = database.get_index_type().indices().get(); + const auto &account_itr = account_idx.find(swdo.sidechain_from); + if (account_itr == account_idx.end()) { + return; + } } ilog("Deposit to process: ${swdo}", ("swdo", swdo)); @@ -532,9 +566,10 @@ void sidechain_net_handler::settle_sidechain_transactions() { ilog("Sidechain transaction to settle: ${sto}", ("sto", sto.id)); - int64_t settle_amount = settle_sidechain_transaction(sto); + asset settle_amount; + bool settle_sidechain_result = settle_sidechain_transaction(sto, settle_amount); - if (settle_amount < 0) { + if (settle_sidechain_result == false) { wlog("Sidechain transaction not settled: ${sto}", ("sto", sto.id)); return; } @@ -551,12 +586,12 @@ void sidechain_net_handler::settle_sidechain_transactions() { sts_op.sidechain_transaction_id = sto.id; proposal_op.proposed_ops.emplace_back(sts_op); - if (settle_amount != 0) { + if (settle_amount.amount != 0) { if (sto.object_id.is()) { asset_issue_operation ai_op; ai_op.fee = asset(2001000); ai_op.issuer = gpo.parameters.son_account(); - ai_op.asset_to_issue = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); + ai_op.asset_to_issue = settle_amount; ai_op.issue_to_account = database.get(sto.object_id).peerplays_from; proposal_op.proposed_ops.emplace_back(ai_op); } @@ -565,7 +600,7 @@ void sidechain_net_handler::settle_sidechain_transactions() { asset_reserve_operation ar_op; ar_op.fee = asset(2001000); ar_op.payer = gpo.parameters.son_account(); - ar_op.amount_to_reserve = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); + ar_op.amount_to_reserve = settle_amount; proposal_op.proposed_ops.emplace_back(ar_op); } } @@ -583,4 +618,63 @@ void sidechain_net_handler::settle_sidechain_transactions() { }); } +void sidechain_net_handler::on_applied_block(const signed_block &b) { + + const chain::global_property_object &gpo = plugin.database().get_global_properties(); + + for (const auto &trx : b.transactions) { + size_t operation_index = -1; + for (auto op : trx.operations) { + operation_index = operation_index + 1; + if (op.which() == operation::tag::value) { + transfer_operation transfer_op = op.get(); + + if (transfer_op.to != gpo.parameters.son_account()) { + continue; + } + + bool is_tracked_asset = + ((sidechain == sidechain_type::bitcoin) && (transfer_op.amount.asset_id == gpo.parameters.btc_asset())) || + ((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hbd_asset())) || + ((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hive_asset())); + + if (!is_tracked_asset) { + continue; + } + + std::string sidechain_from = object_id_to_string(transfer_op.from); + std::string memo = ""; + if (transfer_op.memo) { + memo = transfer_op.memo->get_message(fc::ecc::private_key(), public_key_type()); + boost::trim(memo); + if (!memo.empty()) { + sidechain_from = memo; + } + } + + std::stringstream ss; + ss << "peerplays" + << "-" << trx.id().str() << "-" << operation_index; + std::string sidechain_uid = ss.str(); + + sidechain_event_data sed; + sed.timestamp = database.head_block_time(); + sed.block_num = database.head_block_num(); + sed.sidechain = sidechain_type::peerplays; + sed.sidechain_uid = sidechain_uid; + sed.sidechain_transaction_id = trx.id().str(); + sed.sidechain_from = sidechain_from; + sed.sidechain_to = object_id_to_string(transfer_op.to); + sed.sidechain_currency = object_id_to_string(transfer_op.amount.asset_id); + sed.sidechain_amount = transfer_op.amount.amount; + sed.peerplays_from = transfer_op.from; + sed.peerplays_to = transfer_op.to; + price asset_price = database.get(transfer_op.amount.asset_id).options.core_exchange_rate; + sed.peerplays_asset = asset(transfer_op.amount.amount * asset_price.base.amount / asset_price.quote.amount); + sidechain_event_data_received(sed); + } + } + } +} + }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 59fa01fd..ca4e9149 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -26,13 +26,14 @@ namespace graphene { namespace peerplays_sidechain { // ============================================================================= -bitcoin_rpc_client::bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password) : +bitcoin_rpc_client::bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password, bool _debug_rpc_calls) : ip(_ip), rpc_port(_rpc), user(_user), password(_password), wallet(_wallet), - wallet_password(_wallet_password) { + wallet_password(_wallet_password), + debug_rpc_calls(_debug_rpc_calls) { authorization.key = "Authorization"; authorization.val = "Basic " + fc::base64_encode(user + ":" + password); } @@ -51,7 +52,7 @@ std::string bitcoin_rpc_client::addmultisigaddress(const uint32_t nrequired, con params = params + pubkeys + std::string("]"); body = body + params + std::string(", null, \"bech32\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -83,7 +84,7 @@ std::string bitcoin_rpc_client::combinepsbt(const vector &psbts) { params = params + std::string("\"") + psbt + std::string("\""); } body = body + params + std::string("]] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -120,7 +121,7 @@ std::string bitcoin_rpc_client::createmultisig(const uint32_t nrequired, const s params = params + pubkeys + std::string("]"); body = body + params + std::string(", \"p2sh-segwit\" ] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -162,7 +163,7 @@ std::string bitcoin_rpc_client::createpsbt(const std::vector &ins, co } body += std::string("]] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -206,7 +207,7 @@ std::string bitcoin_rpc_client::createrawtransaction(const std::vector bitcoin_rpc_client::listunspent(const uint32_t minconf, c "\"listunspent\", \"params\": [" + std::to_string(minconf) + "," + std::to_string(maxconf) + "] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); std::vector result; @@ -617,7 +618,7 @@ std::vector bitcoin_rpc_client::listunspent_by_address_and_amount(con body += std::to_string(minimum_amount); body += std::string("} ] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); std::vector result; if (reply.body.empty()) { @@ -652,7 +653,7 @@ std::string bitcoin_rpc_client::loadwallet(const std::string &filename) { "\"loadwallet\", \"params\": [\"" + filename + "\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -680,7 +681,7 @@ std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) { "\"method\": \"sendrawtransaction\", \"params\": [") + std::string("\"") + tx_hex + std::string("\"") + std::string("] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -707,7 +708,7 @@ std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string & std::string params = "\"" + tx_hash + "\""; body = body + params + std::string("]}"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -733,7 +734,7 @@ std::string bitcoin_rpc_client::unloadwallet(const std::string &filename) { "\"unloadwallet\", \"params\": [\"" + filename + "\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -760,7 +761,7 @@ std::string bitcoin_rpc_client::unloadwallet(const std::string &filename) { // std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletlock\", \"method\": " // "\"walletlock\", \"params\": [] }"); // -// const auto reply = send_post_request(body); +// const auto reply = send_post_request(body, debug_rpc_calls); // // if (reply.body.empty()) { // wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -788,7 +789,7 @@ std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { "\"walletprocesspsbt\", \"params\": [\"" + tx_psbt + "\"] }"); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, debug_rpc_calls); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -814,7 +815,7 @@ std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { // "\"walletpassphrase\", \"params\": [\"" + // passphrase + "\", " + std::to_string(timeout) + "] }"); // -// const auto reply = send_post_request(body); +// const auto reply = send_post_request(body, debug_rpc_calls); // // if (reply.body.empty()) { // wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -911,6 +912,10 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::bitcoin; + if (options.count("debug-rpc-calls")) { + debug_rpc_calls = options.at("debug-rpc-calls").as(); + } + ip = options.at("bitcoin-node-ip").as(); zmq_port = options.at("bitcoin-node-zmq-port").as(); rpc_port = options.at("bitcoin-node-rpc-port").as(); @@ -945,7 +950,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain FC_ASSERT(false); } - bitcoin_client = std::unique_ptr(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password)); + bitcoin_client = std::unique_ptr(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password, debug_rpc_calls)); if (!wallet.empty()) { bitcoin_client->loadwallet(wallet); } @@ -989,7 +994,7 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() { bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) { - ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); + //ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); bool should_approve = false; @@ -1094,7 +1099,7 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) if (swdo != idx.end()) { std::string swdo_txid = swdo->sidechain_transaction_id; - std::string swdo_address = swdo->sidechain_to; + std::string swdo_address = swdo->sidechain_from; uint64_t swdo_amount = swdo->sidechain_amount.value; uint64_t swdo_vout = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1)); @@ -1382,7 +1387,7 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() { plugin.app().p2p_node()->broadcast(net::trx_message(trx)); retval = true; } catch (fc::exception &e) { - elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + elog("Sending transaction for sidechain address update operation failed with exception ${e}", ("e", e.what())); retval = false; } } @@ -1487,16 +1492,15 @@ std::string sidechain_net_handler_bitcoin::send_sidechain_transaction(const side return send_transaction(sto); } -int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain_transaction_object &sto) { +bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { if (sto.object_id.is()) { - return 0; + settle_amount = asset(0, database.get_global_properties().parameters.btc_asset()); + return true; } - int64_t settle_amount = -1; - if (sto.sidechain_transaction.empty()) { - return settle_amount; + return false; } std::string tx_str = bitcoin_client->getrawtransaction(sto.sidechain_transaction, true); @@ -1505,7 +1509,7 @@ int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidech boost::property_tree::read_json(tx_ss, tx_json); if ((tx_json.count("error")) && (!tx_json.get_child("error").empty())) { - return settle_amount; + return false; } const chain::global_property_object &gpo = database.get_global_properties(); @@ -1536,15 +1540,17 @@ int64_t sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidech } } } - settle_amount = tx_amount; + settle_amount = asset(tx_amount, database.get_global_properties().parameters.btc_asset()); + return true; } if (sto.object_id.is()) { auto swwo = database.get(sto.object_id); - settle_amount = swwo.withdraw_amount.value; + settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.btc_asset()); + return true; } } - return settle_amount; + return false; } std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const std::vector &son_pubkeys) { @@ -1570,7 +1576,17 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const s std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address) { - std::stringstream prev_sw_ss(prev_swo.addresses.find(sidechain_type::bitcoin)->second); + const auto &address_data = prev_swo.addresses.find(sidechain_type::bitcoin); + if (address_data == prev_swo.addresses.end()) { + return ""; + } + + std::string s = address_data->second; + if (s.empty()) { + return ""; + } + + std::stringstream prev_sw_ss(s); boost::property_tree::ptree prev_sw_pt; boost::property_tree::read_json(prev_sw_ss, prev_sw_pt); std::string prev_pw_address = prev_sw_pt.get("address"); @@ -1615,7 +1631,7 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_ return ""; } //Get redeem script for deposit address - std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_to); + std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_from); std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second; std::stringstream ss(pw_address_json); @@ -1807,8 +1823,8 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) sed.sidechain = addr_itr->sidechain; sed.sidechain_uid = sidechain_uid; sed.sidechain_transaction_id = v.out.hash_tx; - sed.sidechain_from = ""; - sed.sidechain_to = v.address; + sed.sidechain_from = v.address; + sed.sidechain_to = ""; sed.sidechain_currency = "BTC"; sed.sidechain_amount = v.out.amount; sed.peerplays_from = addr_itr->sidechain_address_account; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp new file mode 100644 index 00000000..3b3701dd --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_hive.cpp @@ -0,0 +1,971 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace graphene { namespace peerplays_sidechain { + +std::string resolve_host_addr(const std::string &host_name) { + using namespace boost::asio; + io_service service; + ip::tcp::resolver resolver(service); + auto query = ip::tcp::resolver::query(host_name, std::string()); + auto iter = resolver.resolve(query); + auto endpoint = *iter; + auto addr = ((ip::tcp::endpoint)endpoint).address(); + return addr.to_string(); +} + +std::string strip_proto_name(const std::string &url, std::string *schema) { + auto index = url.find("://"); + if (index == std::string::npos) { + if (schema) + schema->clear(); + return url; + } + if (schema) + schema->assign(&url[0], &url[index + 3]); + return url.substr(index + 3); +} + +}} // namespace graphene::peerplays_sidechain + +namespace graphene { namespace peerplays_sidechain { + +hive_node_rpc_client::hive_node_rpc_client(std::string _ip, uint32_t _port, std::string _user, std::string _password, bool _debug_rpc_calls) : + rpc_client(_ip, _port, _user, _password, _debug_rpc_calls) { +} + +std::string hive_node_rpc_client::account_history_api_get_transaction(std::string transaction_id) { + std::string params = "{ \"id\": \"" + transaction_id + "\" }"; + return send_post_request("account_history_api.get_transaction", params, debug_rpc_calls); +} + +std::string hive_node_rpc_client::block_api_get_block(uint32_t block_number) { + std::string params = "{ \"block_num\": " + std::to_string(block_number) + " }"; + return send_post_request("block_api.get_block", params, debug_rpc_calls); +} + +std::string hive_node_rpc_client::condenser_api_get_accounts(std::vector accounts) { + std::string params = ""; + for (auto account : accounts) { + if (!params.empty()) { + params = params + ","; + } + params = "\"" + account + "\""; + } + params = "[[" + params + "]]"; + return send_post_request("condenser_api.get_accounts", params, debug_rpc_calls); +} + +std::string hive_node_rpc_client::condenser_api_get_config() { + std::string params = "[]"; + return send_post_request("condenser_api.get_config", params, debug_rpc_calls); +} + +std::string hive_node_rpc_client::database_api_get_dynamic_global_properties() { + return send_post_request("database_api.get_dynamic_global_properties", "", debug_rpc_calls); +} + +std::string hive_node_rpc_client::database_api_get_version() { + return send_post_request("database_api.get_version", "", debug_rpc_calls); +} + +std::string hive_node_rpc_client::network_broadcast_api_broadcast_transaction(std::string htrx) { + std::string params = "{ \"trx\": " + htrx + ", \"max_block_age\": -1 }"; + return send_post_request("network_broadcast_api.broadcast_transaction", params, debug_rpc_calls); +} + +std::string hive_node_rpc_client::get_account(std::string account) { + std::vector accounts; + accounts.push_back(account); + std::string reply_str = condenser_api_get_accounts(accounts); + return retrieve_array_value_from_reply(reply_str, "", 0); +} + +std::string hive_node_rpc_client::get_account_memo_key(std::string account) { + std::string reply_str = get_account(account); + reply_str = "{\"result\":" + reply_str + "}"; + return retrieve_value_from_reply(reply_str, "memo_key"); +} + +std::string hive_node_rpc_client::get_chain_id() { + std::string reply_str = database_api_get_version(); + return retrieve_value_from_reply(reply_str, "chain_id"); +} + +std::string hive_node_rpc_client::get_head_block_id() { + std::string reply_str = database_api_get_dynamic_global_properties(); + return retrieve_value_from_reply(reply_str, "head_block_id"); +} + +std::string hive_node_rpc_client::get_head_block_time() { + std::string reply_str = database_api_get_dynamic_global_properties(); + return retrieve_value_from_reply(reply_str, "time"); +} + +std::string hive_node_rpc_client::get_is_test_net() { + std::string reply_str = condenser_api_get_config(); + return retrieve_value_from_reply(reply_str, "IS_TEST_NET"); +} + +std::string hive_node_rpc_client::get_last_irreversible_block_num() { + std::string reply_str = database_api_get_dynamic_global_properties(); + return retrieve_value_from_reply(reply_str, "last_irreversible_block_num"); +} + +sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : + sidechain_net_handler(_plugin, options) { + sidechain = sidechain_type::hive; + + if (options.count("debug-rpc-calls")) { + debug_rpc_calls = options.at("debug-rpc-calls").as(); + } + + node_ip = options.at("hive-node-ip").as(); + node_rpc_port = options.at("hive-node-rpc-port").as(); + if (options.count("hive-node-rpc-user")) { + node_rpc_user = options.at("hive-node-rpc-user").as(); + } else { + node_rpc_user = ""; + } + if (options.count("hive-node-rpc-password")) { + node_rpc_password = options.at("hive-node-rpc-password").as(); + } else { + node_rpc_password = ""; + } + + if (options.count("hive-private-key")) { + const std::vector pub_priv_keys = options["hive-private-key"].as>(); + for (const std::string &itr_key_pair : pub_priv_keys) { + auto key_pair = graphene::app::dejsonify>(itr_key_pair, 5); + ilog("Hive Public Key: ${public}", ("public", key_pair.first)); + if (!key_pair.first.length() || !key_pair.second.length()) { + FC_THROW("Invalid public private key pair."); + } + private_keys[key_pair.first] = key_pair.second; + } + } + + node_rpc_client = new hive_node_rpc_client(node_ip, node_rpc_port, node_rpc_user, node_rpc_password, debug_rpc_calls); + + std::string chain_id_str = node_rpc_client->get_chain_id(); + if (chain_id_str.empty()) { + elog("No Hive node running at ${ip} or wrong rpc port: ${port}", ("ip", node_ip)("port", node_rpc_port)); + FC_ASSERT(false); + } + chain_id = chain_id_type(chain_id_str); + + std::string is_test_net = node_rpc_client->get_is_test_net(); + network_type = is_test_net.compare("true") == 0 ? hive::network::testnet : hive::network::mainnet; + if (network_type == hive::network::mainnet) { + ilog("Running on Hive mainnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str)); + hive::asset::hbd_symbol_ser = HBD_SYMBOL_SER; + hive::asset::hive_symbol_ser = HIVE_SYMBOL_SER; + hive::public_key_type::prefix = KEY_PREFIX_STM; + } else { + ilog("Running on Hive testnet, chain id ${chain_id_str}", ("chain_id_str", chain_id_str)); + hive::asset::hbd_symbol_ser = TBD_SYMBOL_SER; + hive::asset::hive_symbol_ser = TESTS_SYMBOL_SER; + hive::public_key_type::prefix = KEY_PREFIX_TST; + } + + last_block_received = 0; + schedule_hive_listener(); + event_received.connect([this](const std::string &event_data) { + std::thread(&sidechain_net_handler_hive::handle_event, this, event_data).detach(); + }); +} + +sidechain_net_handler_hive::~sidechain_net_handler_hive() { +} + +bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) { + //ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); + + bool should_approve = false; + + const chain::global_property_object &gpo = database.get_global_properties(); + + int32_t op_idx_0 = -1; + chain::operation op_obj_idx_0; + + if (po.proposed_transaction.operations.size() >= 1) { + op_idx_0 = po.proposed_transaction.operations[0].which(); + op_obj_idx_0 = po.proposed_transaction.operations[0]; + } + + int32_t op_idx_1 = -1; + chain::operation op_obj_idx_1; + (void)op_idx_1; + + if (po.proposed_transaction.operations.size() >= 2) { + op_idx_1 = po.proposed_transaction.operations[1].which(); + op_obj_idx_1 = po.proposed_transaction.operations[1]; + } + + switch (op_idx_0) { + + case chain::operation::tag::value: { + bool address_ok = false; + bool transaction_ok = false; + son_wallet_id_type swo_id = op_obj_idx_0.get().son_wallet_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swo = idx.find(swo_id); + if (swo != idx.end()) { + + auto active_sons = gpo.active_sons; + vector wallet_sons = swo->sons; + + bool son_sets_equal = (active_sons.size() == wallet_sons.size()); + + if (son_sets_equal) { + for (size_t i = 0; i < active_sons.size(); i++) { + son_sets_equal = son_sets_equal && active_sons.at(i) == wallet_sons.at(i); + } + } + + if (son_sets_equal) { + address_ok = (op_obj_idx_0.get().address == "son-account"); + } + + if (po.proposed_transaction.operations.size() >= 2) { + object_id_type object_id = op_obj_idx_1.get().object_id; + std::string op_tx_str = op_obj_idx_1.get().transaction; + + const auto &st_idx = database.get_index_type().indices().get(); + const auto st = st_idx.find(object_id); + if (st == st_idx.end()) { + + std::string tx_str = ""; + + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swo = idx.find(object_id); + if (swo != idx.end()) { + + std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str)); + hive::signed_transaction op_trx; + fc::raw::unpack(ss_trx, op_trx, 1000); + + fc::flat_map account_auths; + uint32_t total_weight = 0; + for (const auto &wallet_son : wallet_sons) { + total_weight = total_weight + wallet_son.weight; + account_auths[wallet_son.sidechain_public_keys.at(sidechain)] = wallet_son.weight; + } + + std::string memo_key = node_rpc_client->get_account_memo_key("son-account"); + + hive::authority active; + active.weight_threshold = total_weight * 2 / 3 + 1; + active.account_auths = account_auths; + + hive::account_update_operation auo; + auo.account = "son-account"; + auo.active = active; + auo.memo_key = op_trx.operations[0].get().memo_key; + + hive::signed_transaction htrx; + htrx.ref_block_num = op_trx.ref_block_num; + htrx.ref_block_prefix = op_trx.ref_block_prefix; + htrx.set_expiration(op_trx.expiration); + + htrx.operations.push_back(auo); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + tx_str = boost::algorithm::hex(ss.str()); + } + } + + transaction_ok = (op_tx_str == tx_str); + } + } else { + transaction_ok = true; + } + } + + should_approve = address_ok && + transaction_ok; + break; + } + + case chain::operation::tag::value: { + bool process_ok = false; + son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(swdo_id); + if (swdo != idx.end()) { + + std::string swdo_txid = swdo->sidechain_transaction_id; + std::string swdo_sidechain_from = swdo->sidechain_from; + std::string swdo_sidechain_currency = swdo->sidechain_currency; + uint64_t swdo_sidechain_amount = swdo->sidechain_amount.value; + uint64_t swdo_op_idx = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-"))); + + std::string tx_str = node_rpc_client->account_history_api_get_transaction(swdo_txid); + if (tx_str != "") { + + std::stringstream ss_tx(tx_str); + boost::property_tree::ptree tx; + boost::property_tree::read_json(ss_tx, tx); + + uint64_t op_idx = -1; + for (const auto &ops : tx.get_child("result.operations")) { + const auto &op = ops.second; + op_idx = op_idx + 1; + if (op_idx == swdo_op_idx) { + std::string operation_type = op.get("type"); + + if (operation_type == "transfer_operation") { + const auto &op_value = op.get_child("value"); + + std::string sidechain_from = op_value.get("from"); + + const auto &amount_child = op_value.get_child("amount"); + + uint64_t amount = amount_child.get("amount"); + std::string nai = amount_child.get("nai"); + std::string sidechain_currency = ""; + if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) { + sidechain_currency = "HBD"; + } + if ((nai == "@@000000021") /*?? HIVE*/ || (nai == "@@000000021" /*TESTS*/)) { + sidechain_currency = "HIVE"; + } + + std::string memo = op_value.get("memo"); + boost::trim(memo); + if (!memo.empty()) { + sidechain_from = memo; + } + + process_ok = (swdo_sidechain_from == sidechain_from) && + (swdo_sidechain_currency == sidechain_currency) && + (swdo_sidechain_amount == amount); + } + } + } + } + } + should_approve = process_ok; + break; + } + + case chain::operation::tag::value: { + bool process_ok = false; + bool transaction_ok = false; + son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get().son_wallet_withdraw_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(swwo_id); + if (swwo != idx.end()) { + + uint32_t swwo_block_num = swwo->block_num; + std::string swwo_peerplays_transaction_id = swwo->peerplays_transaction_id; + uint32_t swwo_op_idx = std::stoll(swwo->peerplays_uid.substr(swwo->peerplays_uid.find_last_of("-") + 1)); + + const auto &block = database.fetch_block_by_number(swwo_block_num); + + for (const auto &tx : block->transactions) { + if (tx.id().str() == swwo_peerplays_transaction_id) { + operation op = tx.operations[swwo_op_idx]; + transfer_operation t_op = op.get(); + + price asset_price = database.get(t_op.amount.asset_id).options.core_exchange_rate; + asset peerplays_asset = asset(t_op.amount.amount * asset_price.base.amount / asset_price.quote.amount); + + process_ok = (t_op.to == gpo.parameters.son_account()) && + (swwo->peerplays_from == t_op.from) && + (swwo->peerplays_asset == peerplays_asset); + break; + } + } + + object_id_type object_id = op_obj_idx_1.get().object_id; + std::string op_tx_str = op_obj_idx_1.get().transaction; + + const auto &st_idx = database.get_index_type().indices().get(); + const auto st = st_idx.find(object_id); + if (st == st_idx.end()) { + + std::string tx_str = ""; + + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(object_id); + if (swwo != idx.end()) { + + std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str)); + hive::signed_transaction op_trx; + fc::raw::unpack(ss_trx, op_trx, 1000); + + uint64_t symbol = 0; + if (swwo->withdraw_currency == "HBD") { + symbol = hive::asset::hbd_symbol_ser; + } + if (swwo->withdraw_currency == "HIVE") { + symbol = hive::asset::hive_symbol_ser; + } + + hive::transfer_operation t_op; + t_op.from = "son-account"; + t_op.to = swwo->withdraw_address; + t_op.amount.amount = swwo->withdraw_amount; + t_op.amount.symbol = symbol; + t_op.memo = ""; + + hive::signed_transaction htrx; + htrx.ref_block_num = op_trx.ref_block_num; + htrx.ref_block_prefix = op_trx.ref_block_prefix; + htrx.set_expiration(op_trx.expiration); + + htrx.operations.push_back(t_op); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + tx_str = boost::algorithm::hex(ss.str()); + } + } + + transaction_ok = (op_tx_str == tx_str); + } + } + + should_approve = process_ok && + transaction_ok; + break; + } + + case chain::operation::tag::value: { + should_approve = true; + son_id_type signer = op_obj_idx_0.get().signer; + std::string signature = op_obj_idx_0.get().signature; + sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get().sidechain_transaction_id; + const auto &st_idx = database.get_index_type().indices().get(); + const auto sto = st_idx.find(sidechain_transaction_id); + if (sto == st_idx.end()) { + should_approve = false; + break; + } + + const auto &s_idx = database.get_index_type().indices().get(); + const auto son = s_idx.find(signer); + if (son == s_idx.end()) { + should_approve = false; + break; + } + + break; + } + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + default: + should_approve = false; + elog("=================================================="); + elog("Proposal not considered for approval ${po}", ("po", po)); + elog("=================================================="); + } + + return should_approve; +} + +void sidechain_net_handler_hive::process_primary_wallet() { + const auto &swi = database.get_index_type().indices().get(); + const auto &active_sw = swi.rbegin(); + if (active_sw != swi.rend()) { + + if ((active_sw->addresses.find(sidechain) == active_sw->addresses.end()) || + (active_sw->addresses.at(sidechain).empty())) { + + if (proposal_exists(chain::operation::tag::value, active_sw->id)) { + return; + } + + const chain::global_property_object &gpo = database.get_global_properties(); + + auto active_sons = gpo.active_sons; + fc::flat_map account_auths; + uint32_t total_weight = 0; + for (const auto &active_son : active_sons) { + total_weight = total_weight + active_son.weight; + account_auths[active_son.sidechain_public_keys.at(sidechain)] = active_son.weight; + } + + std::string memo_key = node_rpc_client->get_account_memo_key("son-account"); + + if (memo_key.empty()) { + return; + } + + hive::authority active; + active.weight_threshold = total_weight * 2 / 3 + 1; + active.account_auths = account_auths; + + hive::account_update_operation auo; + auo.account = "son-account"; + auo.active = active; + auo.memo_key = hive::public_key_type(memo_key); + + std::string block_id_str = node_rpc_client->get_head_block_id(); + hive::block_id_type head_block_id(block_id_str); + + std::string head_block_time_str = node_rpc_client->get_head_block_time(); + time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str); + + hive::signed_transaction htrx; + htrx.set_reference_block(head_block_id); + htrx.set_expiration(head_block_time + fc::seconds(180)); + + htrx.operations.push_back(auo); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + std::string tx_str = boost::algorithm::hex(ss.str()); + if (tx_str.empty()) { + return; + } + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; + proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); + + son_wallet_update_operation swu_op; + swu_op.payer = gpo.parameters.son_account(); + swu_op.son_wallet_id = active_sw->id; + swu_op.sidechain = sidechain; + swu_op.address = "son-account"; + + proposal_op.proposed_ops.emplace_back(swu_op); + + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = active_sw->id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + + proposal_op.proposed_ops.emplace_back(stc_op); + + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + } catch (fc::exception &e) { + elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what())); + return; + } + } + } +} + +void sidechain_net_handler_hive::process_sidechain_addresses() { + const auto &sidechain_addresses_idx = database.get_index_type(); + const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get(); + const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain); + std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second, + [&](const sidechain_address_object &sao) { + bool retval = true; + if (sao.expires == time_point_sec::maximum()) { + if (sao.deposit_address == "") { + sidechain_address_update_operation op; + op.payer = plugin.get_current_son_object().son_account; + op.sidechain_address_id = sao.id; + op.sidechain_address_account = sao.sidechain_address_account; + op.sidechain = sao.sidechain; + op.deposit_public_key = sao.deposit_public_key; + op.deposit_address = sao.withdraw_address; + op.deposit_address_data = sao.withdraw_address; + op.withdraw_public_key = sao.withdraw_public_key; + op.withdraw_address = sao.withdraw_address; + + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + retval = true; + } catch (fc::exception &e) { + elog("Sending transaction for sidechain address update operation failed with exception ${e}", ("e", e.what())); + retval = false; + } + } + } + return retval; + }); +} + +bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object &swdo) { + const chain::global_property_object &gpo = database.get_global_properties(); + + price asset_price; + asset asset_to_issue; + if (swdo.sidechain_currency == "HBD") { + asset_price = database.get(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate; + asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, database.get_global_properties().parameters.hbd_asset()); + } + if (swdo.sidechain_currency == "HIVE") { + asset_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; + asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, database.get_global_properties().parameters.hive_asset()); + } + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; + proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); + + son_wallet_deposit_process_operation swdp_op; + swdp_op.payer = gpo.parameters.son_account(); + swdp_op.son_wallet_deposit_id = swdo.id; + proposal_op.proposed_ops.emplace_back(swdp_op); + + asset_issue_operation ai_op; + ai_op.fee = asset(2001000); + ai_op.issuer = gpo.parameters.son_account(); + ai_op.asset_to_issue = asset_to_issue; + ai_op.issue_to_account = swdo.peerplays_from; + proposal_op.proposed_ops.emplace_back(ai_op); + + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return true; + } catch (fc::exception &e) { + elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + return false; + } + + return false; +} + +bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_object &swwo) { + const chain::global_property_object &gpo = database.get_global_properties(); + + //===== + + uint64_t symbol = 0; + if (swwo.withdraw_currency == "HBD") { + symbol = hive::asset::hbd_symbol_ser; + } + if (swwo.withdraw_currency == "HIVE") { + symbol = hive::asset::hive_symbol_ser; + } + + hive::transfer_operation t_op; + t_op.from = "son-account"; + t_op.to = swwo.withdraw_address; + t_op.amount.amount = swwo.withdraw_amount; + t_op.amount.symbol = symbol; + t_op.memo = ""; + + std::string block_id_str = node_rpc_client->get_head_block_id(); + hive::block_id_type head_block_id(block_id_str); + + std::string head_block_time_str = node_rpc_client->get_head_block_time(); + time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str); + + hive::signed_transaction htrx; + htrx.set_reference_block(head_block_id); + htrx.set_expiration(head_block_time + fc::seconds(180)); + + htrx.operations.push_back(t_op); + + std::stringstream ss; + fc::raw::pack(ss, htrx, 1000); + std::string tx_str = boost::algorithm::hex(ss.str()); + if (tx_str.empty()) { + return false; + } + + //===== + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; + proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); + + son_wallet_withdraw_process_operation swwp_op; + swwp_op.payer = gpo.parameters.son_account(); + swwp_op.son_wallet_withdraw_id = swwo.id; + proposal_op.proposed_ops.emplace_back(swwp_op); + + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = swwo.id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + proposal_op.proposed_ops.emplace_back(stc_op); + + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return true; + } catch (fc::exception &e) { + elog("Sending proposal for withdraw sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + return false; + } + + return false; +} + +std::string sidechain_net_handler_hive::process_sidechain_transaction(const sidechain_transaction_object &sto) { + std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); + hive::signed_transaction htrx; + fc::raw::unpack(ss_trx, htrx, 1000); + + std::string chain_id_str = node_rpc_client->get_chain_id(); + const hive::chain_id_type chain_id(chain_id_str); + + fc::optional privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))); + signature_type st = htrx.sign(*privkey, chain_id); + + std::stringstream ss_st; + fc::raw::pack(ss_st, st, 1000); + std::string st_str = boost::algorithm::hex(ss_st.str()); + + return st_str; +} + +std::string sidechain_net_handler_hive::send_sidechain_transaction(const sidechain_transaction_object &sto) { + std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); + hive::signed_transaction htrx; + fc::raw::unpack(ss_trx, htrx, 1000); + + for (auto signature : sto.signatures) { + if (!signature.second.empty()) { + std::stringstream ss_st(boost::algorithm::unhex(signature.second)); + signature_type st; + fc::raw::unpack(ss_st, st, 1000); + htrx.signatures.push_back(st); + } + } + + std::string params = fc::json::to_string(htrx); + node_rpc_client->network_broadcast_api_broadcast_transaction(params); + + return htrx.id().str(); +} + +bool sidechain_net_handler_hive::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { + if (sto.object_id.is()) { + settle_amount.amount = 0; + return true; + } + + if (sto.sidechain_transaction.empty()) { + return false; + } + + std::string tx_str = node_rpc_client->account_history_api_get_transaction(sto.sidechain_transaction); + if (tx_str != "") { + + std::stringstream ss_tx(tx_str); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(ss_tx, tx_json); + + //const chain::global_property_object &gpo = database.get_global_properties(); + + std::string tx_txid = tx_json.get("result.transaction_id"); + uint32_t tx_block_num = tx_json.get("result.block_num"); + uint32_t last_irreversible_block = std::stoul(node_rpc_client->get_last_irreversible_block_num()); + + //std::string tx_address = addr.get_address(); + //int64_t tx_amount = -1; + + if (tx_block_num <= last_irreversible_block) { + if (sto.object_id.is()) { + auto swwo = database.get(sto.object_id); + if (swwo.withdraw_currency == "HBD") { + settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.hbd_asset()); + } + if (swwo.withdraw_currency == "HIVE") { + settle_amount = asset(swwo.withdraw_amount, database.get_global_properties().parameters.hive_asset()); + } + return true; + } + } + } + return false; +} + +void sidechain_net_handler_hive::schedule_hive_listener() { + fc::time_point now = fc::time_point::now(); + int64_t time_to_next = 1000; + + fc::time_point next_wakeup(now + fc::milliseconds(time_to_next)); + + _listener_task = fc::schedule([this] { + hive_listener_loop(); + }, + next_wakeup, "SON Hive listener task"); +} + +void sidechain_net_handler_hive::hive_listener_loop() { + schedule_hive_listener(); + + std::string reply = node_rpc_client->database_api_get_dynamic_global_properties(); + if (!reply.empty()) { + std::stringstream ss(reply); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + if (json.count("result")) { + uint64_t head_block_number = json.get("result.head_block_number"); + if (head_block_number != last_block_received) { + std::string event_data = std::to_string(head_block_number); + handle_event(event_data); + last_block_received = head_block_number; + } + } + } + + //std::string reply = node_rpc_client->get_last_irreversible_block_num(); + //if (!reply.empty()) { + // uint64_t last_irreversible_block = std::stoul(reply); + // if (last_irreversible_block != last_block_received) { + // std::string event_data = std::to_string(last_irreversible_block); + // handle_event(event_data); + // last_block_received = last_irreversible_block; + // } + //} +} + +void sidechain_net_handler_hive::handle_event(const std::string &event_data) { + std::string block = node_rpc_client->block_api_get_block(std::atoll(event_data.c_str())); + if (block != "") { + std::stringstream ss(block); + boost::property_tree::ptree block_json; + boost::property_tree::read_json(ss, block_json); + + size_t tx_idx = -1; + for (const auto &tx_ids_child : block_json.get_child("result.block.transactions")) { + boost::property_tree::ptree tx = tx_ids_child.second; + tx_idx = tx_idx + 1; + + size_t op_idx = -1; + for (const auto &ops : tx.get_child("operations")) { + const auto &op = ops.second; + op_idx = op_idx + 1; + + std::string operation_type = op.get("type"); + + if (operation_type == "transfer_operation") { + const auto &op_value = op.get_child("value"); + + std::string from = op_value.get("from"); + std::string to = op_value.get("to"); + + if (to == "son-account") { + + const auto &amount_child = op_value.get_child("amount"); + + uint64_t amount = amount_child.get("amount"); + //uint64_t precision = amount_child.get("precision"); + std::string nai = amount_child.get("nai"); + std::string sidechain_currency = ""; + price sidechain_currency_price = {}; + if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) { + sidechain_currency = "HBD"; + sidechain_currency_price = database.get(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate; + } + if ((nai == "@@000000021") /*?? HIVE*/ || (nai == "@@000000021" /*TESTS*/)) { + sidechain_currency = "HIVE"; + sidechain_currency_price = database.get(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate; + } + + std::string memo = op_value.get("memo"); + boost::trim(memo); + if (!memo.empty()) { + from = memo; + } + + const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); + const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum())); + account_id_type accn = account_id_type(); + if (addr_itr == sidechain_addresses_idx.end()) { + const auto &account_idx = database.get_index_type().indices().get(); + const auto &account_itr = account_idx.find(from); + if (account_itr == account_idx.end()) { + continue; + } else { + accn = account_itr->id; + } + } else { + accn = addr_itr->sidechain_address_account; + } + + std::vector transaction_ids; + for (const auto &tx_ids_child : block_json.get_child("result.block.transaction_ids")) { + const auto &transaction_id = tx_ids_child.second.get_value(); + transaction_ids.push_back(transaction_id); + } + std::string transaction_id = transaction_ids.at(tx_idx); + + std::stringstream ss; + ss << "hive" + << "-" << transaction_id << "-" << op_idx; + std::string sidechain_uid = ss.str(); + + sidechain_event_data sed; + sed.timestamp = database.head_block_time(); + sed.block_num = database.head_block_num(); + sed.sidechain = sidechain; + sed.sidechain_uid = sidechain_uid; + sed.sidechain_transaction_id = transaction_id; + sed.sidechain_from = from; + sed.sidechain_to = to; + sed.sidechain_currency = sidechain_currency; + sed.sidechain_amount = amount; + sed.peerplays_from = accn; + sed.peerplays_to = database.get_global_properties().parameters.son_account(); + sed.peerplays_asset = asset(sed.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount); + sidechain_event_data_received(sed); + } + } + } + } + } +} + +}} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 1bbce500..d5a9ec32 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -25,6 +25,15 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::peerplays; + //const auto &assets_by_symbol = database.get_index_type().indices().get(); + //const auto get_asset_id = [&assets_by_symbol](const string &symbol) { + // auto asset_itr = assets_by_symbol.find(symbol); + // FC_ASSERT(asset_itr != assets_by_symbol.end(), "Unable to find asset '${sym}'", ("sym", symbol)); + // return asset_itr->get_id(); + //}; + //tracked_assets.push_back(get_asset_id("PBTC")); + //tracked_assets.push_back(get_asset_id("PETH")); + //tracked_assets.push_back(get_asset_id("PEOS")); if (options.count("peerplays-private-key")) { const std::vector pub_priv_keys = options["peerplays-private-key"].as>(); @@ -37,10 +46,6 @@ sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidec private_keys[key_pair.first] = key_pair.second; } } - - database.applied_block.connect([&](const signed_block &b) { - on_applied_block(b); - }); } sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() { @@ -131,34 +136,34 @@ void sidechain_net_handler_peerplays::process_sidechain_addresses() { const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain); std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second, [&](const sidechain_address_object &sao) { - bool retval = true; + bool retval = true; if (sao.expires == time_point_sec::maximum()) { if (sao.deposit_address == "") { sidechain_address_update_operation op; - op.payer = plugin.get_current_son_object().son_account; - op.sidechain_address_id = sao.id; - op.sidechain_address_account = sao.sidechain_address_account; - op.sidechain = sao.sidechain; - op.deposit_public_key = sao.deposit_public_key; - op.deposit_address = sao.withdraw_address; - op.deposit_address_data = sao.withdraw_address; - op.withdraw_public_key = sao.withdraw_public_key; - op.withdraw_address = sao.withdraw_address; + op.payer = plugin.get_current_son_object().son_account; + op.sidechain_address_id = sao.id; + op.sidechain_address_account = sao.sidechain_address_account; + op.sidechain = sao.sidechain; + op.deposit_public_key = sao.deposit_public_key; + op.deposit_address = sao.withdraw_address; + op.deposit_address_data = sao.withdraw_address; + op.withdraw_public_key = sao.withdraw_public_key; + op.withdraw_address = sao.withdraw_address; - signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op); - try { - trx.validate(); - database.push_transaction(trx, database::validation_steps::skip_block_size_check); - if (plugin.app().p2p_node()) - plugin.app().p2p_node()->broadcast(net::trx_message(trx)); - retval = true; - } catch (fc::exception &e) { - elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what())); - retval = false; - } + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + retval = true; + } catch (fc::exception &e) { + elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what())); + retval = false; + } } } - return retval; + return retval; }); return; } @@ -266,45 +271,23 @@ std::string sidechain_net_handler_peerplays::send_sidechain_transaction(const si return ""; } -int64_t sidechain_net_handler_peerplays::settle_sidechain_transaction(const sidechain_transaction_object &sto) { - int64_t settle_amount = 0; - return settle_amount; -} +bool sidechain_net_handler_peerplays::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { -void sidechain_net_handler_peerplays::on_applied_block(const signed_block &b) { - for (const auto &trx : b.transactions) { - size_t operation_index = -1; - for (auto op : trx.operations) { - operation_index = operation_index + 1; - if (op.which() == operation::tag::value) { - transfer_operation transfer_op = op.get(); - if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) { - continue; - } - - std::stringstream ss; - ss << "peerplays" - << "-" << trx.id().str() << "-" << operation_index; - std::string sidechain_uid = ss.str(); - - sidechain_event_data sed; - sed.timestamp = database.head_block_time(); - sed.block_num = database.head_block_num(); - sed.sidechain = sidechain_type::peerplays; - sed.sidechain_uid = sidechain_uid; - sed.sidechain_transaction_id = trx.id().str(); - sed.sidechain_from = fc::to_string(transfer_op.from.space_id) + "." + fc::to_string(transfer_op.from.type_id) + "." + fc::to_string((uint64_t)transfer_op.from.instance); - sed.sidechain_to = fc::to_string(transfer_op.to.space_id) + "." + fc::to_string(transfer_op.to.type_id) + "." + fc::to_string((uint64_t)transfer_op.to.instance); - sed.sidechain_currency = fc::to_string(transfer_op.amount.asset_id.space_id) + "." + fc::to_string(transfer_op.amount.asset_id.type_id) + "." + fc::to_string((uint64_t)transfer_op.amount.asset_id.instance); - sed.sidechain_amount = transfer_op.amount.amount; - sed.peerplays_from = transfer_op.from; - sed.peerplays_to = transfer_op.to; - price asset_price = database.get(transfer_op.amount.asset_id).options.core_exchange_rate; - sed.peerplays_asset = asset(transfer_op.amount.amount * asset_price.base.amount / asset_price.quote.amount); - sidechain_event_data_received(sed); - } - } + if (sto.object_id.is()) { + settle_amount = asset(0); } + + if (sto.object_id.is()) { + //auto swdo = database.get(sto.object_id); + //settle_amount = asset(swdo.sidechain_amount, swdo.sidechain_currency); + } + + if (sto.object_id.is()) { + auto swwo = database.get(sto.object_id); + settle_amount = swwo.peerplays_asset; + } + + return true; } }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 962488a6..ff876b0c 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace graphene { namespace peerplays_sidechain { @@ -10,6 +11,10 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_manager::sidechain_net_manager(peerplays_sidechain_plugin &_plugin) : plugin(_plugin), database(_plugin.database()) { + + //database.applied_block.connect([&](const signed_block &b) { + // on_applied_block(b); + //}); } sidechain_net_manager::~sidechain_net_manager() { @@ -26,6 +31,12 @@ bool sidechain_net_manager::create_handler(sidechain_type sidechain, const boost ret_val = true; break; } + case sidechain_type::hive: { + std::unique_ptr h = std::unique_ptr(new sidechain_net_handler_hive(plugin, options)); + net_handlers.push_back(std::move(h)); + ret_val = true; + break; + } case sidechain_type::peerplays: { std::unique_ptr h = std::unique_ptr(new sidechain_net_handler_peerplays(plugin, options)); net_handlers.push_back(std::move(h)); @@ -87,4 +98,7 @@ void sidechain_net_manager::settle_sidechain_transactions() { } } +void sidechain_net_manager::on_applied_block(const signed_block &b) { +} + }} // namespace graphene::peerplays_sidechain diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 457aa891..a7921b1f 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -652,7 +652,7 @@ class wallet_api * @see suggest_brain_key() * * @param brain_key Brain key - * @param numberOfDesiredKeys Number of desired keys + * @param number_of_desired_keys Number of desired keys * @return A list of keys that are deterministically derived from the brainkey */ vector derive_owner_keys_from_brain_key(string brain_key, int number_of_desired_keys = 1) const; @@ -667,7 +667,12 @@ class wallet_api bool is_public_key_registered(string public_key) const; /** - * @param role - active | owner | memo + * Gets private key from password + * + * @param account Account name + * @param role Account role - active | owner | memo + * @param password Account password + * @return public/private key pair */ pair get_private_key_from_password( string account, string role, string password )const; @@ -895,18 +900,24 @@ class wallet_api * that it exists in the blockchain. If it exists then it will report the amount received and * who sent it. * - * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from * @param confirmation_receipt - a base58 encoded stealth confirmation + * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from + * @param opt_memo - optional memo */ blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); /** - * Transfers a public balance from @from to one or more blinded balances using a + * Transfers a public balance from from_account_id_or_name to one or more blinded balances using a * stealth transfer. + * + * @param from_account_id_or_name account id or name + * @param asset_symbol asset symbol + * @param to_amounts map from key or label to amount + * @param broadcast true to broadcast the transaction on the network + * @returns blind confirmation structure */ blind_confirmation transfer_to_blind( string from_account_id_or_name, string asset_symbol, - /** map from key or label to amount */ vector> to_amounts, bool broadcast = false ); @@ -1010,11 +1021,11 @@ class wallet_api * * @param buyer_account The account buying the asset for another asset. * @param base The name or id of the asset to buy. - * @param quote The name or id of the assest being offered as payment. + * @param quote The name or id of the asset being offered as payment. * @param rate The rate in base:quote at which you want to buy. * @param amount the amount of base you want to buy. * @param broadcast true to broadcast the transaction on the network. - * @param The signed transaction selling the funds. + * @returns The signed transaction buying the funds. */ signed_transaction buy( string buyer_account, string base, @@ -1467,6 +1478,12 @@ class wallet_api */ map list_active_sons(); + /** + * @brief Get SON network status + * @return SON network status description + */ + map get_son_network_status(); + /** * @brief Get active SON wallet * @return Active SON wallet object @@ -1494,6 +1511,7 @@ class wallet_api * @param account the name or id of the account who owns the address * @param sidechain a sidechain to whom address belongs * @param deposit_public_key sidechain public key used for deposit address + * @param deposit_address sidechain address for deposits * @param withdraw_public_key sidechain public key used for withdraw address * @param withdraw_address sidechain address for withdrawals * @param broadcast true to broadcast the transaction on the network @@ -1502,6 +1520,7 @@ class wallet_api signed_transaction add_sidechain_address(string account, sidechain_type sidechain, string deposit_public_key, + string deposit_address, string withdraw_public_key, string withdraw_address, bool broadcast = false); @@ -1562,7 +1581,7 @@ class wallet_api /** * Update a witness object owned by the given account. * - * @param witness The name of the witness's owner account. Also accepts the ID of the owner account or the ID of the witness. + * @param witness_name The name of the witness's owner account. Also accepts the ID of the owner account or the ID of the witness. * @param url Same as for create_witness. The empty string makes it remain the same. * @param block_signing_key The new block signing public key. The empty string makes it remain the same. * @param broadcast true if you wish to broadcast the transaction. @@ -1600,7 +1619,7 @@ class wallet_api * Update your votes for a worker * * @param account The account which will pay the fee and update votes. - * @param worker_vote_delta {"vote_for" : [...], "vote_against" : [...], "vote_abstain" : [...]} + * @param delta {"vote_for" : [...], "vote_against" : [...], "vote_abstain" : [...]} * @param broadcast true if you wish to broadcast the transaction. */ signed_transaction update_worker_votes( @@ -1733,7 +1752,7 @@ class wallet_api signed_transaction update_son_votes(string voting_account, std::vector sons_to_approve, std::vector sons_to_reject, - uint16_t desired_number_of_son, + uint16_t desired_number_of_sons, bool broadcast = false); /** Vote for a given witness. @@ -1827,8 +1846,8 @@ class wallet_api * set, your preferences will be ignored. * * @param account_to_modify the name or id of the account to update - * @param number_of_committee_members the number - * + * @param desired_number_of_witnesses desired number of witnesses + * @param desired_number_of_committee_members desired number of committee members * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote proxy settings */ @@ -2130,6 +2149,7 @@ class wallet_api /** Creates a new tournament * @param creator the accout that is paying the fee to create the tournament * @param options the options detailing the specifics of the tournament + * @param broadcast true if you wish to broadcast the transaction * @return the signed version of the transaction */ signed_transaction tournament_create( string creator, tournament_options options, bool broadcast = false ); @@ -2169,7 +2189,7 @@ class wallet_api tournament_state state); /** Get specific information about a tournament - * @param tournament_id the ID of the tournament + * @param id the ID of the tournament */ tournament_object get_tournament(tournament_id_type id); @@ -2177,6 +2197,7 @@ class wallet_api * @param game_id the id of the game * @param player_account the name of the player * @param gesture rock, paper, or scissors + * @param broadcast true if you wish to broadcast the transaction * @return the signed version of the transaction */ signed_transaction rps_throw(game_id_type game_id, @@ -2229,6 +2250,9 @@ class wallet_api * @param revenue_split revenue split for the sale * @param is_transferable can transfer the NFT or not * @param is_sellable can sell NFT or not + * @param role_id account role id + * @param max_supply max supply of NTFs + * @param lottery_options lottery options * @param broadcast true to broadcast transaction to the network * @return Signed transaction transfering the funds */ @@ -2256,6 +2280,7 @@ class wallet_api * @param revenue_split revenue split for the sale * @param is_transferable can transfer the NFT or not * @param is_sellable can sell NFT or not + * @param role_id account role id * @param broadcast true to broadcast transaction to the network * @return Signed transaction transfering the funds */ @@ -2369,8 +2394,8 @@ class wallet_api /** * @brief Returns operator approved state for all NFT owned by owner - * @param owner NFT owner account ID - * @param token_id NFT ID + * @param owner_account_id_or_name NFT owner account ID or name + * @param operator_account_id_or_name NFT operator account ID or name * @return True if operator is approved for all NFT owned by owner, else False */ bool nft_is_approved_for_all(string owner_account_id_or_name, string operator_account_id_or_name) const; @@ -2599,6 +2624,7 @@ FC_API( graphene::wallet::wallet_api, (update_son_vesting_balances) (list_sons) (list_active_sons) + (get_son_network_status) (request_son_maintenance) (cancel_request_son_maintenance) (get_active_son_wallet) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 843c9cbc..e876924e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -734,12 +734,16 @@ public: { return _remote_db->get_dynamic_global_properties(); } + std::string object_id_to_string(object_id_type id) const + { + std::string object_id = fc::to_string(id.space()) + + "." + fc::to_string(id.type()) + + "." + fc::to_string(id.instance()); + return object_id; + } std::string account_id_to_string(account_id_type id) const { - std::string account_id = fc::to_string(id.space_id) - + "." + fc::to_string(id.type_id) - + "." + fc::to_string(id.instance.value); - return account_id; + return object_id_to_string(id); } account_object get_account(account_id_type id) const { @@ -2203,6 +2207,40 @@ public: return result; } FC_CAPTURE_AND_RETHROW() } + map get_son_network_status() + { try { + global_property_object gpo = get_global_properties(); + vector son_ids; + son_ids.reserve(gpo.active_sons.size()); + std::transform(gpo.active_sons.begin(), gpo.active_sons.end(), + std::inserter(son_ids, son_ids.end()), + [](const son_info& swi) { + return swi.son_id; + }); + + map result; + std::vector> son_objects = _remote_db->get_sons(son_ids); + for(auto son_obj: son_objects) { + string status; + if (son_obj) { + son_statistics_object sso = get_object(son_obj->statistics); + if (sso.last_active_timestamp + fc::seconds(gpo.parameters.son_heartbeat_frequency()) > time_point::now()) { + status = "OK, regular SON heartbeat"; + } else { + if (sso.last_active_timestamp + fc::seconds(gpo.parameters.son_down_time()) > time_point::now()) { + status = "OK, irregular SON heartbeat, but not triggering SON down proposal"; + } else { + status = "NOT OK, irregular SON heartbeat, triggering SON down proposal"; + } + } + } else { + status = "NOT OK, invalid SON id"; + } + result[son_obj->id] = status; + } + return result; + } FC_CAPTURE_AND_RETHROW() } + optional get_active_son_wallet() { try { return _remote_db->get_active_son_wallet(); @@ -2221,6 +2259,7 @@ public: signed_transaction add_sidechain_address(string account, sidechain_type sidechain, string deposit_public_key, + string deposit_address, string withdraw_public_key, string withdraw_address, bool broadcast /* = false */) @@ -2232,6 +2271,7 @@ public: op.sidechain_address_account = sidechain_address_account_id; op.sidechain = sidechain; op.deposit_public_key = deposit_public_key; + op.deposit_address = deposit_address; op.withdraw_public_key = withdraw_public_key; op.withdraw_address = withdraw_address; @@ -5041,6 +5081,11 @@ map wallet_api::list_active_sons() return my->list_active_sons(); } +map wallet_api::get_son_network_status() +{ + return my->get_son_network_status(); +} + optional wallet_api::get_active_son_wallet() { return my->get_active_son_wallet(); @@ -5059,11 +5104,12 @@ vector> wallet_api::get_son_wallets(uint32_t limit) signed_transaction wallet_api::add_sidechain_address(string account, sidechain_type sidechain, string deposit_public_key, + string deposit_address, string withdraw_public_key, string withdraw_address, bool broadcast /* = false */) { - return my->add_sidechain_address(account, sidechain, deposit_public_key, withdraw_public_key, withdraw_address, broadcast); + return my->add_sidechain_address(account, sidechain, deposit_public_key, deposit_address, withdraw_public_key, withdraw_address, broadcast); } signed_transaction wallet_api::delete_sidechain_address(string account, diff --git a/tests/cli/son.cpp b/tests/cli/son.cpp index cf4fd8ed..fed39e86 100644 --- a/tests/cli/son.cpp +++ b/tests/cli/son.cpp @@ -121,10 +121,12 @@ BOOST_AUTO_TEST_CASE( create_sons ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); auto son1_obj = con.wallet_api_ptr->get_son("son1account"); @@ -153,6 +155,7 @@ BOOST_AUTO_TEST_CASE( cli_update_son ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; son_test_helper sth(*this); sth.create_son("sonmember", "http://sonmember", sidechain_public_keys); @@ -167,6 +170,7 @@ BOOST_AUTO_TEST_CASE( cli_update_son ) // update SON sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; con.wallet_api_ptr->update_son("sonmember", "http://sonmember_updated", "", sidechain_public_keys, true); son_data = con.wallet_api_ptr->get_son("sonmember"); @@ -197,10 +201,12 @@ BOOST_AUTO_TEST_CASE( son_voting ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); BOOST_TEST_MESSAGE("Voting for SONs"); @@ -292,6 +298,7 @@ BOOST_FIXTURE_TEST_CASE( select_top_fifteen_sons, cli_fixture ) { sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i); + sidechain_public_keys[sidechain_type::hive] = "hive account " + fc::to_pretty_string(i); sth.create_son("sonaccount" + fc::to_pretty_string(i), "http://son" + fc::to_pretty_string(i), sidechain_public_keys, @@ -366,10 +373,12 @@ BOOST_AUTO_TEST_CASE( list_son ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); auto res = con.wallet_api_ptr->list_sons("", 100); @@ -396,10 +405,12 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); BOOST_TEST_MESSAGE("Vote for 2 accounts with update_son_votes"); @@ -555,10 +566,12 @@ BOOST_AUTO_TEST_CASE( related_functions ) sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 1"; + sidechain_public_keys[sidechain_type::hive] = "hive account 1"; sth.create_son("son1account", "http://son1", sidechain_public_keys); sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address 2"; + sidechain_public_keys[sidechain_type::hive] = "hive account 2"; sth.create_son("son2account", "http://son2", sidechain_public_keys); gpo = con.wallet_api_ptr->get_global_properties(); @@ -592,6 +605,7 @@ BOOST_FIXTURE_TEST_CASE( cli_list_active_sons, cli_fixture ) { sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i); + sidechain_public_keys[sidechain_type::hive] = "hive account " + fc::to_pretty_string(i); sth.create_son("sonaccount" + fc::to_pretty_string(i), "http://son" + fc::to_pretty_string(i), sidechain_public_keys, @@ -659,6 +673,7 @@ BOOST_AUTO_TEST_CASE( maintenance_test ) { sidechain_public_keys.clear(); sidechain_public_keys[sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i); + sidechain_public_keys[sidechain_type::hive] = "hive account " + fc::to_pretty_string(i); sth.create_son("sonaccount" + fc::to_pretty_string(i), "http://son" + fc::to_pretty_string(i), sidechain_public_keys, diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 5fee05d5..1e3bb7e4 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -491,12 +491,32 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) // Modify the transaction signed statistics of Alice's SON db.modify( *son_stats_obj1, [&]( son_statistics_object& _s) { - _s.txs_signed = 2; + _s.txs_signed[sidechain_type::bitcoin] = 2; + _s.txs_signed[sidechain_type::hive] = 4; + + _s.total_txs_signed[sidechain_type::bitcoin] = 2; + _s.total_txs_signed[sidechain_type::hive] = 4; + + _s.sidechain_txs_reported[sidechain_type::bitcoin] = 4; + _s.sidechain_txs_reported[sidechain_type::hive] = 8; + + _s.total_sidechain_txs_reported[sidechain_type::bitcoin] = 4; + _s.total_sidechain_txs_reported[sidechain_type::hive] = 8; }); // Modify the transaction signed statistics of Bob's SON db.modify( *son_stats_obj2, [&]( son_statistics_object& _s) { - _s.txs_signed = 3; + _s.txs_signed[sidechain_type::bitcoin] = 3; + _s.txs_signed[sidechain_type::hive] = 6; + + _s.total_txs_signed[sidechain_type::bitcoin] = 3; + _s.total_txs_signed[sidechain_type::hive] = 6; + + _s.sidechain_txs_reported[sidechain_type::bitcoin] = 6; + _s.sidechain_txs_reported[sidechain_type::hive] = 12; + + _s.total_sidechain_txs_reported[sidechain_type::bitcoin] = 6; + _s.total_sidechain_txs_reported[sidechain_type::hive] = 12; }); // Note the balances before the maintenance @@ -506,11 +526,23 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) generate_blocks(dpo.next_maintenance_time); generate_block(); // Check if the signed transaction statistics are reset for both SONs - BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed, 0); - BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed, 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->txs_signed.at(sidechain_type::hive), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->txs_signed.at(sidechain_type::hive), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->sidechain_txs_reported.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj1->sidechain_txs_reported.at(sidechain_type::hive), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->sidechain_txs_reported.at(sidechain_type::bitcoin), 0); + BOOST_REQUIRE_EQUAL(son_stats_obj2->sidechain_txs_reported.at(sidechain_type::hive), 0); - BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed, 2); - BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed, 3); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed.at(sidechain_type::bitcoin), 2); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_txs_signed.at(sidechain_type::hive), 4); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed.at(sidechain_type::bitcoin), 3); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_txs_signed.at(sidechain_type::hive), 6); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_sidechain_txs_reported.at(sidechain_type::bitcoin), 4); + BOOST_REQUIRE_EQUAL(son_stats_obj1->total_sidechain_txs_reported.at(sidechain_type::hive), 8); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_sidechain_txs_reported.at(sidechain_type::bitcoin), 6); + BOOST_REQUIRE_EQUAL(son_stats_obj2->total_sidechain_txs_reported.at(sidechain_type::hive), 12); // Check that Alice and Bob are paid for signing the transactions in the previous day/cycle BOOST_REQUIRE_EQUAL(db.get_balance(obj1->son_account, asset_id_type()).amount.value, 80+obj1_balance); BOOST_REQUIRE_EQUAL(db.get_balance(obj2->son_account, asset_id_type()).amount.value, 120+obj2_balance);