SON for Hive

This commit is contained in:
serkixenos 2021-11-18 17:32:30 +00:00
parent 43c29ce1bf
commit ceffe4cf3c
48 changed files with 2626 additions and 1018 deletions

1
.gitignore vendored
View file

@ -14,6 +14,7 @@ data
CMakeDoxyfile.in
build
build__*
libraries/utilities/git_revision.cpp

View file

@ -44,7 +44,6 @@ make -j$(nproc)
make install # this can install the executable files under /usr/local
```
docker build -t peerplays .
## Docker image

View file

@ -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

4
clang-format.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
find ./libraries/plugins/peerplays_sidechain -regex ".*[c|h]pp" | xargs clang-format -i

View file

@ -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<son_stats_index>().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<const son_statistics_object&>(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<son_index>().indices().get<by_id>();
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<son_info>& 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>([](asset_dynamic_data_object& a) {
a.current_supply = 0;
});
const asset_object& hbd_asset =
create<asset_object>( [&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>([](asset_dynamic_data_object& a) {
a.current_supply = 0;
});
const asset_object& hive_asset =
create<asset_object>( [&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<uint64_t>& 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();
}

View file

@ -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

View file

@ -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,

View file

@ -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) )

View file

@ -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)

View file

@ -31,9 +31,9 @@ namespace graphene { namespace chain {
son_id_type owner;
// Lifetime total transactions signed
uint64_t total_txs_signed = 0;
flat_map<sidechain_type, uint64_t> total_txs_signed;
// Transactions signed since the last son payouts
uint64_t txs_signed = 0;
flat_map<sidechain_type, uint64_t> 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<sidechain_type, uint64_t> total_sidechain_txs_reported;
// Sidechain transactions reported by this SON
uint64_t sidechain_txs_reported = 0;
flat_map<sidechain_type, uint64_t> sidechain_txs_reported;
};
/**

View file

@ -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());

View file

@ -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<sidechain_address_index>().indices().get<by_sidechain_and_deposit_public_key_and_expires>();
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();

View file

@ -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>([&](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;

View file

@ -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));
}
}}

View file

@ -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<son_stats_index>().indices().get<by_owner>().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<son_stats_index>().indices().get<by_owner>().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;
}

View file

@ -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<son_stats_index>().indices().get<by_owner>().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<son_stats_index>().indices().get<by_owner>().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;
}

View file

@ -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" )

View file

@ -1,6 +1,6 @@
#include <fc/io/raw.hpp>
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_script.hpp>
#include <graphene/peerplays_sidechain/bitcoin/serialize.hpp>
#include <fc/io/raw.hpp>
namespace graphene { namespace peerplays_sidechain { namespace bitcoin {

View file

@ -0,0 +1,185 @@
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
#include <sstream>
#include <string>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <curl/curl.h>
#include <fc/crypto/base64.hpp>
#include <fc/log/logger.hpp>
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<std::string>(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

View file

@ -0,0 +1,8 @@
#include <graphene/peerplays_sidechain/common/utils.hpp>
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;
}

View file

@ -0,0 +1,69 @@
#include <graphene/peerplays_sidechain/hive/asset.hpp>
#include <fc/io/json.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
#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<std::string>(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<std::string>(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<std::string>(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<std::string>(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<int64_t>(v_object[ASSET_AMOUNT_KEY].as<std::string>(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<std::string>(max_depth) == HBD_NAI) {
vo.symbol = graphene::peerplays_sidechain::hive::asset::hbd_symbol_ser;
}
if (v_object[ASSET_NAI_KEY].as<std::string>(max_depth) == HIVE_NAI) {
vo.symbol = graphene::peerplays_sidechain::hive::asset::hive_symbol_ser;
}
}
FC_CAPTURE_AND_RETHROW()
}
} // namespace fc

View file

@ -0,0 +1,101 @@
#include <graphene/peerplays_sidechain/hive/operations.hpp>
#include <fc/io/raw.hpp>
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 <typename T>
void operator()(const T &v) const {
auto name = trim_typename_namespace(fc::get_typename<T>::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 <typename T>
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 <typename T>
void operator()(T &v) const {
name = trim_typename_namespace(fc::get_typename<T>::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<string, int64_t> to_tag = []() {
std::map<string, int64_t> 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

View file

@ -0,0 +1,57 @@
#include <graphene/peerplays_sidechain/hive/transaction.hpp>
#include <boost/algorithm/hex.hpp>
#include <fc/bitutil.hpp>
#include <fc/io/raw.hpp>
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

View file

@ -0,0 +1,73 @@
#include <graphene/peerplays_sidechain/hive/types.hpp>
#include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/exception/exception.hpp>
#include <fc/io/raw.hpp>
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<binary_key>(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

View file

@ -0,0 +1,39 @@
#pragma once
#include <cstdint>
#include <string>
#include <fc/network/http/connection.hpp>
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

View file

@ -0,0 +1,5 @@
#pragma once
#include <graphene/chain/protocol/asset.hpp>
std::string object_id_to_string(graphene::chain::object_id_type id);

View file

@ -0,0 +1,41 @@
#pragma once
#include <graphene/peerplays_sidechain/hive/types.hpp>
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))

View file

@ -0,0 +1,33 @@
#pragma once
#include <cstdint>
#include <fc/container/flat_fwd.hpp>
#include <graphene/peerplays_sidechain/hive/types.hpp>
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<hive::account_name_type, uint16_t> account_auths;
fc::flat_map<hive::public_key_type, uint16_t> 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))

View file

@ -0,0 +1,123 @@
#pragma once
#include <cstdint>
#include <vector>
#include <fc/optional.hpp>
#include <graphene/chain/protocol/types.hpp>
#include <graphene/peerplays_sidechain/hive/asset.hpp>
#include <graphene/peerplays_sidechain/hive/authority.hpp>
#include <graphene/peerplays_sidechain/hive/types.hpp>
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<authority> owner;
fc::optional<authority> active;
fc::optional<authority> 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))

View file

@ -0,0 +1,69 @@
#pragma once
#include <graphene/peerplays_sidechain/hive/hive_operations.hpp>
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)

View file

@ -0,0 +1,44 @@
#pragma once
#include <cstdint>
#include <vector>
#include <fc/container/flat_fwd.hpp>
#include <fc/time.hpp>
#include <graphene/peerplays_sidechain/hive/operations.hpp>
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<hive_operation> 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<fc::ecc::compact_signature> 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))

View file

@ -0,0 +1,72 @@
#pragma once
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/ripemd160.hpp>
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<void_t> future_extensions;
typedef fc::flat_set<future_extensions> 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<int64_t> share_type;
//typedef safe<uint64_t> 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)

View file

@ -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<detail::peerplays_sidechain_plugin_impl> my;

View file

@ -4,7 +4,6 @@
#include <boost/program_options.hpp>
#include <fc/signals.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/sidechain_address_object.hpp>
#include <graphene/chain/sidechain_transaction_object.hpp>
@ -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<std::string, std::string> private_keys;
void on_applied_block(const signed_block &b);
private:
};

View file

@ -1,13 +1,14 @@
#pragma once
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
#include <string>
#include <zmq.hpp>
#include <boost/signals2.hpp>
#include <fc/network/http/connection.hpp>
#include <fc/signals.hpp>
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp>
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<std::string> public_keys);
std::string combinepsbt(const vector<std::string> &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<void(const std::string &)> event_received;
boost::signals2::signal<void(const std::string &)> 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;

View file

@ -0,0 +1,68 @@
#pragma once
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
#include <string>
#include <boost/signals2.hpp>
#include <fc/network/http/connection.hpp>
#include <graphene/peerplays_sidechain/common/rpc_client.hpp>
#include <graphene/peerplays_sidechain/hive/types.hpp>
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<std::string> 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<void> _listener_task;
boost::signals2::signal<void(const std::string &)> event_received;
void schedule_hive_listener();
void hive_listener_loop();
void handle_event(const std::string &event_data);
};
}} // namespace graphene::peerplays_sidechain

View file

@ -4,8 +4,6 @@
#include <string>
#include <fc/signals.hpp>
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

View file

@ -29,6 +29,8 @@ private:
peerplays_sidechain_plugin &plugin;
graphene::chain::database &database;
std::vector<std::unique_ptr<sidechain_net_handler>> net_handlers;
void on_applied_block(const signed_block &b);
};
}} // namespace graphene::peerplays_sidechain

View file

@ -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<chain::son_id_type> &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<peerplays_sidechain::sidechain_net_manager> 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<uint32_t>().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<string>(), ("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<vector<string>>()->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<uint16_t>()->default_value(150), "Sidechain retry throttling threshold");
cli.add_options()("debug-rpc-calls", bpo::value<bool>()->default_value(false), "Outputs RPC calls to console");
cli.add_options()("bitcoin-sidechain-enabled", bpo::value<bool>()->default_value(false), "Bitcoin sidechain handler enabled");
cli.add_options()("bitcoin-node-ip", bpo::value<string>()->default_value("127.0.0.1"), "IP address of Bitcoin node");
cli.add_options()("bitcoin-node-zmq-port", bpo::value<uint32_t>()->default_value(11111), "ZMQ port of Bitcoin node");
cli.add_options()("bitcoin-node-rpc-port", bpo::value<uint32_t>()->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<string>(), "Bitcoin wallet password");
cli.add_options()("bitcoin-private-key", bpo::value<vector<string>>()->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<uint16_t>()->default_value(150), "Sidechain retry throttling threshold");
cli.add_options()("hive-sidechain-enabled", bpo::value<bool>()->default_value(false), "Hive sidechain handler enabled");
cli.add_options()("hive-node-ip", bpo::value<string>()->default_value("127.0.0.1"), "Hive node IP address");
cli.add_options()("hive-node-rpc-port", bpo::value<uint32_t>()->default_value(28090), "Hive node RPC port");
cli.add_options()("hive-node-rpc-user", bpo::value<string>(), "Hive node RPC user");
cli.add_options()("hive-node-rpc-password", bpo::value<string>(), "Hive node RPC password");
cli.add_options()("hive-private-key", bpo::value<vector<string>>()->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<uint16_t>();
if (options.count("sidechain-retry-threshold")) {
retries_threshold = options.at("sidechain-retry-threshold").as<uint16_t>();
}
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<bool>();
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<bool>();
//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<bool>();
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<bool>();
#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<sidechain_net_manager>(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<chain::son_id_type> &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<chain::son_id_type> &peerplays_sidechain_plugin::get_sons() {
return my->get_sons();
}

View file

@ -1,14 +1,21 @@
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
#include <boost/algorithm/string.hpp>
#include <fc/log/logger.hpp>
#include <graphene/chain/chain_property_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/peerplays_sidechain/common/utils.hpp>
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<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
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<asset_object>(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<asset_object>(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<asset_object>(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<asset_object>(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<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
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<account_index>().indices().get<by_name>();
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<son_wallet_deposit_id_type>()) {
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<son_wallet_deposit_object>(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<transfer_operation>::value) {
transfer_operation transfer_op = op.get<transfer_operation>();
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<asset_object>(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

View file

@ -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<std::string> &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<btc_txout> &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<btc_txout
}
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__));
@ -234,7 +235,7 @@ std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) {
"\"createwallet\", \"params\": [\"" +
wallet_name + "\"] }");
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__));
@ -262,7 +263,7 @@ std::string bitcoin_rpc_client::decodepsbt(std::string const &tx_psbt) {
"\"decodepsbt\", \"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__));
@ -290,7 +291,7 @@ std::string bitcoin_rpc_client::decoderawtransaction(std::string const &tx_hex)
"\"decoderawtransaction\", \"params\": [\"" +
tx_hex + "\"] }");
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__));
@ -318,7 +319,7 @@ std::string bitcoin_rpc_client::encryptwallet(const std::string &passphrase) {
"\"encryptwallet\", \"params\": [\"" +
passphrase + "\"] }");
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__));
@ -346,7 +347,7 @@ uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
"\"method\": \"estimatesmartfee\", \"params\": [" +
std::to_string(conf_target) + 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__));
@ -383,7 +384,7 @@ std::string bitcoin_rpc_client::finalizepsbt(std::string const &tx_psbt) {
"\"finalizepsbt\", \"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__));
@ -409,7 +410,7 @@ std::string bitcoin_rpc_client::getaddressinfo(const std::string &address) {
"\"getaddressinfo\", \"params\": [\"" +
address + "\"] }");
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__));
@ -437,7 +438,7 @@ std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t
"\"getblock\", \"params\": [\"" +
block_hash + "\", " + std::to_string(verbosity) + "] }");
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__));
@ -467,7 +468,7 @@ std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const
std::string params = "\"" + txid + "\", " + (verbose ? "true" : "false");
body = body + 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__));
@ -495,7 +496,7 @@ std::string bitcoin_rpc_client::gettransaction(const std::string &txid, const bo
std::string params = "\"" + txid + "\", " + (include_watch_only ? "true" : "false");
body = body + 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__));
@ -520,7 +521,7 @@ std::string bitcoin_rpc_client::getblockchaininfo() {
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getblockchaininfo\", \"method\": "
"\"getblockchaininfo\", \"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__));
@ -553,7 +554,7 @@ void bitcoin_rpc_client::importaddress(const std::string &address_or_script, con
(p2sh ? "true" : "false");
body = body + 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__));
@ -576,7 +577,7 @@ std::vector<btc_txout> 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<btc_txout> result;
@ -617,7 +618,7 @@ std::vector<btc_txout> 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<btc_txout> 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<bool>();
}
ip = options.at("bitcoin-node-ip").as<std::string>();
zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>();
rpc_port = options.at("bitcoin-node-rpc-port").as<uint32_t>();
@ -945,7 +950,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
FC_ASSERT(false);
}
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(new bitcoin_rpc_client(ip, rpc_port, rpc_user, rpc_password, wallet, wallet_password));
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>(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<son_wallet_id_type>()) {
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<son_wallet_withdraw_id_type>()) {
auto swwo = database.get<son_wallet_withdraw_object>(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_info> &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<std::string>("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;

View file

@ -0,0 +1,971 @@
#include <graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp>
#include <algorithm>
#include <iomanip>
#include <thread>
#include <boost/algorithm/hex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <fc/crypto/base64.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/io/json.hpp>
#include <fc/log/logger.hpp>
#include <fc/network/ip.hpp>
#include <fc/smart_ref_impl.hpp>
#include <fc/time.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp>
#include <graphene/chain/protocol/son_wallet.hpp>
#include <graphene/chain/son_info.hpp>
#include <graphene/chain/son_wallet_object.hpp>
#include <graphene/peerplays_sidechain/common/utils.hpp>
#include <graphene/peerplays_sidechain/hive/asset.hpp>
#include <graphene/peerplays_sidechain/hive/operations.hpp>
#include <graphene/peerplays_sidechain/hive/transaction.hpp>
#include <graphene/utilities/key_conversion.hpp>
#include <boost/asio.hpp>
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<std::string> 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<std::string> 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<bool>();
}
node_ip = options.at("hive-node-ip").as<std::string>();
node_rpc_port = options.at("hive-node-rpc-port").as<uint32_t>();
if (options.count("hive-node-rpc-user")) {
node_rpc_user = options.at("hive-node-rpc-user").as<std::string>();
} else {
node_rpc_user = "";
}
if (options.count("hive-node-rpc-password")) {
node_rpc_password = options.at("hive-node-rpc-password").as<std::string>();
} else {
node_rpc_password = "";
}
if (options.count("hive-private-key")) {
const std::vector<std::string> pub_priv_keys = options["hive-private-key"].as<std::vector<std::string>>();
for (const std::string &itr_key_pair : pub_priv_keys) {
auto key_pair = graphene::app::dejsonify<std::pair<std::string, std::string>>(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<chain::son_wallet_update_operation>::value: {
bool address_ok = false;
bool transaction_ok = false;
son_wallet_id_type swo_id = op_obj_idx_0.get<son_wallet_update_operation>().son_wallet_id;
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
const auto swo = idx.find(swo_id);
if (swo != idx.end()) {
auto active_sons = gpo.active_sons;
vector<son_info> 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<son_wallet_update_operation>().address == "son-account");
}
if (po.proposed_transaction.operations.size() >= 2) {
object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
const auto st = st_idx.find(object_id);
if (st == st_idx.end()) {
std::string tx_str = "";
if (object_id.is<son_wallet_id_type>()) {
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
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<std::string, uint16_t> 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<hive::account_update_operation>().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<chain::son_wallet_deposit_process_operation>::value: {
bool process_ok = false;
son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get<son_wallet_deposit_process_operation>().son_wallet_deposit_id;
const auto &idx = database.get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
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<std::string>("type");
if (operation_type == "transfer_operation") {
const auto &op_value = op.get_child("value");
std::string sidechain_from = op_value.get<std::string>("from");
const auto &amount_child = op_value.get_child("amount");
uint64_t amount = amount_child.get<uint64_t>("amount");
std::string nai = amount_child.get<std::string>("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<std::string>("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<chain::son_wallet_withdraw_process_operation>::value: {
bool process_ok = false;
bool transaction_ok = false;
son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get<son_wallet_withdraw_process_operation>().son_wallet_withdraw_id;
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
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<transfer_operation>();
price asset_price = database.get<asset_object>(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<sidechain_transaction_create_operation>().object_id;
std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
const auto st = st_idx.find(object_id);
if (st == st_idx.end()) {
std::string tx_str = "";
if (object_id.is<son_wallet_withdraw_id_type>()) {
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
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<chain::sidechain_transaction_sign_operation>::value: {
should_approve = true;
son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer;
std::string signature = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signature;
sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id;
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_id>();
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<son_index>().indices().get<by_id>();
const auto son = s_idx.find(signer);
if (son == s_idx.end()) {
should_approve = false;
break;
}
break;
}
case chain::operation::tag<chain::sidechain_transaction_settle_operation>::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<son_wallet_index>().indices().get<by_id>();
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<chain::son_wallet_update_operation>::value, active_sw->id)) {
return;
}
const chain::global_property_object &gpo = database.get_global_properties();
auto active_sons = gpo.active_sons;
fc::flat_map<std::string, uint16_t> 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<sidechain_address_index>();
const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
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<asset_object>(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<asset_object>(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<fc::ecc::private_key> 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<son_wallet_id_type>()) {
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<std::string>("result.transaction_id");
uint32_t tx_block_num = tx_json.get<uint32_t>("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<son_wallet_withdraw_id_type>()) {
auto swwo = database.get<son_wallet_withdraw_object>(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<uint64_t>("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<std::string>("type");
if (operation_type == "transfer_operation") {
const auto &op_value = op.get_child("value");
std::string from = op_value.get<std::string>("from");
std::string to = op_value.get<std::string>("to");
if (to == "son-account") {
const auto &amount_child = op_value.get_child("amount");
uint64_t amount = amount_child.get<uint64_t>("amount");
//uint64_t precision = amount_child.get<uint64_t>("precision");
std::string nai = amount_child.get<std::string>("nai");
std::string sidechain_currency = "";
price sidechain_currency_price = {};
if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) {
sidechain_currency = "HBD";
sidechain_currency_price = database.get<asset_object>(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<asset_object>(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate;
}
std::string memo = op_value.get<std::string>("memo");
boost::trim(memo);
if (!memo.empty()) {
from = memo;
}
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
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<account_index>().indices().get<by_name>();
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<std::string> 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<std::string>();
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

View file

@ -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<asset_index>().indices().get<by_symbol>();
//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<std::string> pub_priv_keys = options["peerplays-private-key"].as<std::vector<std::string>>();
@ -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<transfer_operation>::value) {
transfer_operation transfer_op = op.get<transfer_operation>();
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<asset_object>(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<son_wallet_id_type>()) {
settle_amount = asset(0);
}
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
//auto swdo = database.get<son_wallet_deposit_object>(sto.object_id);
//settle_amount = asset(swdo.sidechain_amount, swdo.sidechain_currency);
}
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
auto swwo = database.get<son_wallet_withdraw_object>(sto.object_id);
settle_amount = swwo.peerplays_asset;
}
return true;
}
}} // namespace graphene::peerplays_sidechain

View file

@ -3,6 +3,7 @@
#include <fc/log/logger.hpp>
#include <graphene/chain/son_wallet_object.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp>
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<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(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<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(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

View file

@ -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<brain_key_info> 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<public_key_type,string> 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<pair<string, string>> 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<string, son_id_type> list_active_sons();
/**
* @brief Get SON network status
* @return SON network status description
*/
map<son_id_type, string> 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<std::string> sons_to_approve,
std::vector<std::string> 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)

View file

@ -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<son_id_type, string> get_son_network_status()
{ try {
global_property_object gpo = get_global_properties();
vector<son_id_type> 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<son_id_type, string> result;
std::vector<fc::optional<son_object>> 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<son_wallet_object> 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<string, son_id_type> wallet_api::list_active_sons()
return my->list_active_sons();
}
map<son_id_type, string> wallet_api::get_son_network_status()
{
return my->get_son_network_status();
}
optional<son_wallet_object> wallet_api::get_active_son_wallet()
{
return my->get_active_son_wallet();
@ -5059,11 +5104,12 @@ vector<optional<son_wallet_object>> 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,

View file

@ -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,

View file

@ -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);