Merge remote-tracking branch 'origin/beatrice'
This commit is contained in:
commit
bf67aecc88
130 changed files with 12345 additions and 215871 deletions
|
|
@ -29,6 +29,18 @@ build:
|
|||
tags:
|
||||
- builder
|
||||
|
||||
dockerize:
|
||||
stage: build
|
||||
script:
|
||||
- docker build . -t $DOCKER_REPO:$CI_COMMIT_REF_NAME
|
||||
- docker login -u $DOCKER_USER -p $DOCKER_PASS
|
||||
- docker push $DOCKER_REPO:$CI_COMMIT_REF_NAME
|
||||
- docker logout
|
||||
tags:
|
||||
- builder
|
||||
when: manual
|
||||
timeout: 3h
|
||||
|
||||
test:
|
||||
stage: test
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
sonar.projectKey=peerplays-network_peerplays
|
||||
sonar.organization=peerplays-network
|
||||
|
||||
# This is the name and version displayed in the SonarCloud UI.
|
||||
sonar.projectName=peerplays
|
||||
|
||||
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
|
||||
sonar.sources=.
|
||||
|
||||
sonar.host.url=https://sonarcloud.io
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
# Defines BitShares library target.
|
||||
project( BitShares )
|
||||
# Defines Peerplays library target.
|
||||
project( Peerplays )
|
||||
cmake_minimum_required( VERSION 2.8.12 )
|
||||
|
||||
set( BLOCKCHAIN_NAME "BitShares" )
|
||||
set( BLOCKCHAIN_NAME "Peerplays" )
|
||||
|
||||
set( CLI_CLIENT_EXECUTABLE_NAME graphene_client )
|
||||
set( GUI_CLIENT_EXECUTABLE_NAME BitShares )
|
||||
set( GUI_CLIENT_EXECUTABLE_NAME Peerplays )
|
||||
set( CUSTOM_URL_SCHEME "gcs" )
|
||||
set( INSTALLER_APP_ID "68ad7005-8eee-49c9-95ce-9eed97e5b347" )
|
||||
|
||||
|
|
@ -22,6 +22,34 @@ endif()
|
|||
|
||||
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" )
|
||||
|
||||
# function to help with cUrl
|
||||
macro(FIND_CURL)
|
||||
if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set (CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
||||
find_package(CURL REQUIRED)
|
||||
list(APPEND CURL_LIBRARIES ${OPENSSL_LIBRARIES} ${BOOST_THREAD_LIBRARY} ${CMAKE_DL_LIBS})
|
||||
set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES})
|
||||
else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB)
|
||||
find_package(CURL REQUIRED)
|
||||
endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB)
|
||||
|
||||
if( WIN32 )
|
||||
if ( MSVC )
|
||||
list( APPEND CURL_LIBRARIES Wldap32 )
|
||||
endif( MSVC )
|
||||
|
||||
if( MINGW )
|
||||
# MinGW requires a specific order of included libraries ( CURL before ZLib )
|
||||
find_package( ZLIB REQUIRED )
|
||||
list( APPEND CURL_LIBRARIES ${ZLIB_LIBRARY} pthread )
|
||||
endif( MINGW )
|
||||
|
||||
list( APPEND CURL_LIBRARIES ${PLATFORM_SPECIFIC_LIBS} )
|
||||
endif( WIN32 )
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS "ON")
|
||||
set(GRAPHENE_EGENESIS_JSON "${CMAKE_CURRENT_SOURCE_DIR}/genesis.json" CACHE PATH "location of the genesis.json to embed in the executable" )
|
||||
|
||||
|
|
@ -71,7 +99,7 @@ ENDIF()
|
|||
|
||||
if( WIN32 )
|
||||
|
||||
message( STATUS "Configuring BitShares on WIN32")
|
||||
message( STATUS "Configuring Peerplays on WIN32")
|
||||
set( DB_VERSION 60 )
|
||||
set( BDB_STATIC_LIBS 1 )
|
||||
|
||||
|
|
@ -103,20 +131,13 @@ if( WIN32 )
|
|||
SET(TCL_LIBRARY ${TCL_LIBS})
|
||||
|
||||
else( WIN32 ) # Apple AND Linux
|
||||
|
||||
find_library(READLINE_LIBRARIES NAMES readline)
|
||||
find_path(READLINE_INCLUDE_DIR readline/readline.h)
|
||||
#if(NOT READLINE_INCLUDE_DIR OR NOT READLINE_LIBRARIES)
|
||||
# MESSAGE(FATAL_ERROR "Could not find lib readline.")
|
||||
#endif()
|
||||
|
||||
if( APPLE )
|
||||
# Apple Specific Options Here
|
||||
message( STATUS "Configuring BitShares on OS X" )
|
||||
message( STATUS "Configuring Peerplays on OS X" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -stdlib=libc++ -Wall" )
|
||||
else( APPLE )
|
||||
# Linux Specific Options Here
|
||||
message( STATUS "Configuring BitShares on Linux" )
|
||||
message( STATUS "Configuring Peerplays on Linux" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -Wall" )
|
||||
set( rt_library rt )
|
||||
#set( pthread_library pthread)
|
||||
|
|
@ -135,7 +156,7 @@ else( WIN32 ) # Apple AND Linux
|
|||
endif( APPLE )
|
||||
|
||||
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp -Wno-parentheses -Wno-terminate -Wno-invalid-offsetof -Wno-sign-compare" )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
|
||||
elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||
if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 )
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" )
|
||||
|
|
@ -154,7 +175,7 @@ else( WIN32 ) # Apple AND Linux
|
|||
|
||||
endif( WIN32 )
|
||||
|
||||
set(ENABLE_COVERAGE_TESTING FALSE CACHE BOOL "Build BitShares for code coverage analysis")
|
||||
set(ENABLE_COVERAGE_TESTING FALSE CACHE BOOL "Build Peerplays for code coverage analysis")
|
||||
|
||||
if(ENABLE_COVERAGE_TESTING)
|
||||
SET(CMAKE_CXX_FLAGS "--coverage ${CMAKE_CXX_FLAGS}")
|
||||
|
|
@ -163,13 +184,13 @@ endif()
|
|||
add_subdirectory( libraries )
|
||||
|
||||
|
||||
set(BUILD_BITSHARES_PROGRAMS TRUE CACHE BOOL "Build bitshares executables (witness node, cli wallet, etc)")
|
||||
set(BUILD_PEERPLAYS_PROGRAMS TRUE CACHE BOOL "Build peerplays executables (witness node, cli wallet, etc)")
|
||||
add_subdirectory( programs )
|
||||
|
||||
set(BUILD_BITSHARES_TESTS TRUE CACHE BOOL "Build bitshares unit tests")
|
||||
if( BUILD_BITSHARES_TESTS )
|
||||
set(BUILD_PEERPLAYS_TESTS TRUE CACHE BOOL "Build peerplays unit tests")
|
||||
if( BUILD_PEERPLAYS_TESTS )
|
||||
add_subdirectory( tests )
|
||||
endif( BUILD_BITSHARES_TESTS )
|
||||
endif( BUILD_PEERPLAYS_TESTS )
|
||||
|
||||
|
||||
if (ENABLE_INSTALLER)
|
||||
|
|
@ -191,18 +212,18 @@ set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
|
|||
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "A client for the BitShares network")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A client for the BitShares network")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "A client for the Peerplays network")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A client for the Peerplays network")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "BitShares ${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Peerplays ${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
if(WIN32)
|
||||
SET(CPACK_GENERATOR "ZIP;NSIS")
|
||||
set(CPACK_PACKAGE_NAME "BitShares") # override above
|
||||
set(CPACK_PACKAGE_NAME "Peerplays") # override above
|
||||
set(CPACK_NSIS_EXECUTABLES_DIRECTORY .)
|
||||
set(CPACK_NSIS_PACKAGE_NAME "BitShares v${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_NSIS_PACKAGE_NAME "Peerplays v${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_NSIS_PACKAGE_NAME}")
|
||||
set(CPACK_NSIS_DEFINES " !define MUI_STARTMENUPAGE_DEFAULTFOLDER \\\"BitShares\\\"")
|
||||
set(CPACK_NSIS_DEFINES " !define MUI_STARTMENUPAGE_DEFAULTFOLDER \\\"Peerplays\\\"")
|
||||
# it seems like windows zip files usually don't have a single directory inside them, unix tgz frequently do
|
||||
SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
|
||||
|
||||
|
|
@ -220,3 +241,4 @@ endif(LINUX)
|
|||
|
||||
include(CPack)
|
||||
endif(ENABLE_INSTALLER)
|
||||
|
||||
|
|
|
|||
343
Doxyfile
343
Doxyfile
|
|
@ -1,4 +1,4 @@
|
|||
# Doxyfile 1.8.9.1
|
||||
# Doxyfile 1.8.17
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
|
|
@ -17,11 +17,11 @@
|
|||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# This tag specifies the encoding used for all characters in the config file
|
||||
# that follow. The default is UTF-8 which is also the encoding used for all text
|
||||
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
|
||||
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
|
||||
# for the list of possible encodings.
|
||||
# This tag specifies the encoding used for all characters in the configuration
|
||||
# file that follow. The default is UTF-8 which is also the encoding used for all
|
||||
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
|
||||
# iconv built into libc) for the transcoding. See
|
||||
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
|
|
@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO
|
|||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all generated output in the proper direction.
|
||||
# Possible values are: None, LTR, RTL and Context.
|
||||
# The default value is: None.
|
||||
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||
# descriptions after the members that are listed in the file and class
|
||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||
|
|
@ -179,6 +187,16 @@ SHORT_NAMES = NO
|
|||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||
# such as
|
||||
# /***************
|
||||
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||
# Javadoc-style will behave just like regular comments and it will not be
|
||||
# interpreted by doxygen.
|
||||
# The default value is: NO.
|
||||
|
||||
JAVADOC_BANNER = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||
|
|
@ -226,7 +244,12 @@ TAB_SIZE = 4
|
|||
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||
# documentation, which will result in a user-defined paragraph with heading
|
||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
||||
# newlines.
|
||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
||||
# alias to insert a newline as if a physical newline was in the original file.
|
||||
# When you need a literal { or } or , in the value part of an alias you have to
|
||||
# escape them by means of a backslash (\), this can lead to conflicts with the
|
||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
||||
# a double escape (\\{ and \\})
|
||||
|
||||
ALIASES =
|
||||
|
||||
|
|
@ -264,17 +287,26 @@ OPTIMIZE_FOR_FORTRAN = NO
|
|||
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
|
||||
# sources only. Doxygen will then generate output that is more tailored for that
|
||||
# language. For instance, namespaces will be presented as modules, types will be
|
||||
# separated into more groups, etc.
|
||||
# The default value is: NO.
|
||||
|
||||
OPTIMIZE_OUTPUT_SLICE = NO
|
||||
|
||||
# Doxygen selects the parser to use depending on the extension of the files it
|
||||
# parses. With this tag you can assign which parser to use for a given
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
||||
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
||||
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
||||
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
||||
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
||||
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
|
|
@ -285,7 +317,7 @@ EXTENSION_MAPPING =
|
|||
|
||||
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
# documentation. See http://daringfireball.net/projects/markdown/ for details.
|
||||
# documentation. See https://daringfireball.net/projects/markdown/ for details.
|
||||
# The output of markdown processing is further processed by doxygen, so you can
|
||||
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
|
||||
# case of backward compatibilities issues.
|
||||
|
|
@ -293,6 +325,15 @@ EXTENSION_MAPPING =
|
|||
|
||||
MARKDOWN_SUPPORT = YES
|
||||
|
||||
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
|
||||
# to that level are automatically included in the table of contents, even if
|
||||
# they do not have an id attribute.
|
||||
# Note: This feature currently applies only to Markdown headings.
|
||||
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
TOC_INCLUDE_HEADINGS = 5
|
||||
|
||||
# When enabled doxygen tries to link words that correspond to documented
|
||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
||||
# be prevented in individual cases by putting a % sign in front of the word or
|
||||
|
|
@ -318,7 +359,7 @@ BUILTIN_STL_SUPPORT = NO
|
|||
CPP_CLI_SUPPORT = NO
|
||||
|
||||
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
|
||||
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
|
||||
# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
|
||||
# will parse them like normal C++ but will assume all classes use public instead
|
||||
# of private inheritance when no explicit protection keyword is present.
|
||||
# The default value is: NO.
|
||||
|
|
@ -343,6 +384,13 @@ IDL_PROPERTY_SUPPORT = YES
|
|||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# If one adds a struct or class to a group and this option is enabled, then also
|
||||
# any nested class or struct is added to the same group. By default this option
|
||||
# is disabled and one has to add nested compounds explicitly via \ingroup.
|
||||
# The default value is: NO.
|
||||
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
|
||||
# (for instance a group of public functions) to be put as a subgroup of that
|
||||
# type (e.g. under the Public Functions section). Set it to NO to prevent
|
||||
|
|
@ -417,6 +465,12 @@ EXTRACT_ALL = YES
|
|||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||
# methods of a class will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PRIV_VIRTUAL = NO
|
||||
|
||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||
# scope will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
|
@ -471,8 +525,8 @@ HIDE_UNDOC_MEMBERS = NO
|
|||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
||||
# included in the documentation.
|
||||
# declarations. If set to NO, these declarations will be included in the
|
||||
# documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
|
|
@ -495,7 +549,7 @@ INTERNAL_DOCS = NO
|
|||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
|
|
@ -682,7 +736,7 @@ LAYOUT_FILE =
|
|||
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
|
||||
# the reference definitions. This must be a list of .bib files. The .bib
|
||||
# extension is automatically appended if omitted. This requires the bibtex tool
|
||||
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
|
||||
# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
|
||||
# For LaTeX the style of the bibliography can be controlled using
|
||||
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
|
||||
# search path. See also \cite for info how to create references.
|
||||
|
|
@ -727,11 +781,18 @@ WARN_IF_DOC_ERROR = YES
|
|||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||
# are documented, but have no documentation for their parameters or return
|
||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
||||
# parameter documentation, but not about the absence of documentation.
|
||||
# parameter documentation, but not about the absence of documentation. If
|
||||
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_NO_PARAMDOC = NO
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
|
||||
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
|
||||
# can produce. The string should contain the $file, $line, and $text tags, which
|
||||
# will be replaced by the file and line number from which the warning originated
|
||||
|
|
@ -755,15 +816,19 @@ WARN_LOGFILE =
|
|||
# The INPUT tag is used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like myfile.cpp or
|
||||
# directories like /usr/src/myproject. Separate the files or directories with
|
||||
# spaces.
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = doc/main.dox libraries/chain libraries/chain/db libraries/app libraries/wallet
|
||||
INPUT = doc/main.dox \
|
||||
libraries/chain \
|
||||
libraries/chain/db \
|
||||
libraries/app \
|
||||
libraries/wallet
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
|
|
@ -771,12 +836,19 @@ INPUT_ENCODING = UTF-8
|
|||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
|
||||
# *.h) to filter out the source-files in the directories. If left blank the
|
||||
# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
|
||||
# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
|
||||
# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
|
||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||
# *.qsf, *.as and *.js.
|
||||
# *.h) to filter out the source-files in the directories.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
|
||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS =
|
||||
|
||||
|
|
@ -862,6 +934,10 @@ IMAGE_PATH =
|
|||
# Note that the filter must not add or remove lines; it is applied before the
|
||||
# code is scanned, but not when the output code is generated. If lines are added
|
||||
# or removed, the anchors will not be placed correctly.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# properly processed by doxygen.
|
||||
|
||||
INPUT_FILTER =
|
||||
|
||||
|
|
@ -871,6 +947,10 @@ INPUT_FILTER =
|
|||
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
|
||||
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
|
||||
# patterns match the file name, INPUT_FILTER is applied.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# properly processed by doxygen.
|
||||
|
||||
FILTER_PATTERNS =
|
||||
|
||||
|
|
@ -923,7 +1003,7 @@ INLINE_SOURCES = NO
|
|||
STRIP_CODE_COMMENTS = YES
|
||||
|
||||
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
|
||||
# function all documented functions referencing it will be listed.
|
||||
# entity all documented functions referencing it will be listed.
|
||||
# The default value is: NO.
|
||||
|
||||
REFERENCED_BY_RELATION = NO
|
||||
|
|
@ -955,12 +1035,12 @@ SOURCE_TOOLTIPS = YES
|
|||
# If the USE_HTAGS tag is set to YES then the references to source code will
|
||||
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
|
||||
# source browser. The htags tool is part of GNU's global source tagging system
|
||||
# (see http://www.gnu.org/software/global/global.html). You will need version
|
||||
# (see https://www.gnu.org/software/global/global.html). You will need version
|
||||
# 4.8.6 or higher.
|
||||
#
|
||||
# To use it do the following:
|
||||
# - Install the latest version of global
|
||||
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
|
||||
# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
|
||||
# - Make sure the INPUT points to the root of the source tree
|
||||
# - Run doxygen as normal
|
||||
#
|
||||
|
|
@ -982,6 +1062,35 @@ USE_HTAGS = NO
|
|||
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||
# cost of reduced performance. This can be particularly helpful with template
|
||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||
# information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
||||
# such as clang-check. These options will then be passed to the parser.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
CLANG_DATABASE_PATH =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1100,7 +1209,7 @@ HTML_EXTRA_FILES =
|
|||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the style sheet and background images according to
|
||||
# this color. Hue is specified as an angle on a colorwheel, see
|
||||
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||
# purple, and 360 is red again.
|
||||
# Minimum value: 0, maximum value: 359, default value: 220.
|
||||
|
|
@ -1129,12 +1238,24 @@ HTML_COLORSTYLE_GAMMA = 80
|
|||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to NO can help when comparing the output of multiple runs.
|
||||
# The default value is: YES.
|
||||
# to YES can help to show when doxygen was last run and thus if the
|
||||
# documentation is up to date.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||
# documentation will contain a main index with vertical navigation menus that
|
||||
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||
# page. Disable this option to support browsers that do not have JavaScript,
|
||||
# like the Qt help browser.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
# page has loaded.
|
||||
|
|
@ -1158,13 +1279,13 @@ HTML_INDEX_NUM_ENTRIES = 100
|
|||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
|
||||
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||
# that directory and running make install will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
|
||||
# for more information.
|
||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||
# genXcode/_index.html for more information.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
|
|
@ -1203,7 +1324,7 @@ DOCSET_PUBLISHER_NAME = Publisher
|
|||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
|
|
@ -1279,7 +1400,7 @@ QCH_FILE =
|
|||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
|
|
@ -1287,7 +1408,7 @@ QHP_NAMESPACE = org.doxygen.Project
|
|||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
|
||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
|
@ -1296,7 +1417,7 @@ QHP_VIRTUAL_FOLDER = doc
|
|||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
|
|
@ -1304,7 +1425,7 @@ QHP_CUST_FILTER_NAME =
|
|||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
|
|
@ -1312,7 +1433,7 @@ QHP_CUST_FILTER_ATTRS =
|
|||
|
||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
|
|
@ -1405,7 +1526,7 @@ EXT_LINKS_IN_WINDOW = NO
|
|||
|
||||
FORMULA_FONTSIZE = 10
|
||||
|
||||
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
|
||||
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
|
||||
# generated for formulas are transparent PNGs. Transparent PNGs are not
|
||||
# supported properly for IE 6.0, but are supported on all modern browsers.
|
||||
#
|
||||
|
|
@ -1416,8 +1537,14 @@ FORMULA_FONTSIZE = 10
|
|||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||
# the section "Including formulas" for details.
|
||||
|
||||
FORMULA_MACROFILE =
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||
# http://www.mathjax.org) which uses client side Javascript for the rendering
|
||||
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||
# installed or if you want to formulas look prettier in the HTML output. When
|
||||
# enabled you may also need to install MathJax separately and configure the path
|
||||
|
|
@ -1444,8 +1571,8 @@ MATHJAX_FORMAT = HTML-CSS
|
|||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from http://www.mathjax.org before deployment.
|
||||
# The default value is: http://cdn.mathjax.org/mathjax/latest.
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
|
|
@ -1487,7 +1614,7 @@ MATHJAX_CODEFILE =
|
|||
SEARCHENGINE = YES
|
||||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a web server instead of a web client using Javascript. There
|
||||
# implemented using a web server instead of a web client using JavaScript. There
|
||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||
|
|
@ -1506,7 +1633,7 @@ SERVER_BASED_SEARCH = NO
|
|||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: http://xapian.org/).
|
||||
# Xapian (see: https://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
|
|
@ -1519,7 +1646,7 @@ EXTERNAL_SEARCH = NO
|
|||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: http://xapian.org/). See the section "External Indexing and
|
||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
|
|
@ -1571,21 +1698,35 @@ LATEX_OUTPUT = latex
|
|||
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
|
||||
# invoked.
|
||||
#
|
||||
# Note that when enabling USE_PDFLATEX this option is only used for generating
|
||||
# bitmaps for formulas in the HTML output, but not in the Makefile that is
|
||||
# written to the output directory.
|
||||
# The default file is: latex.
|
||||
# Note that when not enabling USE_PDFLATEX the default is latex when enabling
|
||||
# USE_PDFLATEX the default is pdflatex and when in the later case latex is
|
||||
# chosen this is overwritten by pdflatex. For specific output languages the
|
||||
# default can have been set differently, this depends on the implementation of
|
||||
# the output language.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_CMD_NAME = latex
|
||||
|
||||
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
|
||||
# index for LaTeX.
|
||||
# Note: This tag is used in the Makefile / make.bat.
|
||||
# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
|
||||
# (.tex).
|
||||
# The default file is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||
# it will be automatically added in the LaTeX code.
|
||||
# Note: This tag is used in the generated output file (.tex).
|
||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||
# The default value is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_MAKEINDEX_CMD = makeindex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
|
||||
# documents. This may be useful for small projects and may help to save some
|
||||
# trees in general.
|
||||
|
|
@ -1604,9 +1745,12 @@ COMPACT_LATEX = NO
|
|||
PAPER_TYPE = a4
|
||||
|
||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||
# that should be included in the LaTeX output. To get the times font for
|
||||
# instance you can specify
|
||||
# EXTRA_PACKAGES=times
|
||||
# that should be included in the LaTeX output. The package can be specified just
|
||||
# by its name or with the correct syntax as to be used with the LaTeX
|
||||
# \usepackage command. To get the times font for instance you can specify :
|
||||
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
|
||||
# To use the option intlimits with the amsmath package you can specify:
|
||||
# EXTRA_PACKAGES=[intlimits]{amsmath}
|
||||
# If left blank no extra packages will be included.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
|
|
@ -1703,12 +1847,28 @@ LATEX_SOURCE_CODE = NO
|
|||
|
||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||
# bibliography, e.g. plainnat, or ieeetr. See
|
||||
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
# The default value is: plain.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_BIB_STYLE = plain
|
||||
|
||||
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to NO can help when comparing the output of multiple runs.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_TIMESTAMP = NO
|
||||
|
||||
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# path from which the emoji images will be read. If a relative path is entered,
|
||||
# it will be relative to the LATEX_OUTPUT directory. If left blank the
|
||||
# LATEX_OUTPUT directory will be used.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1748,9 +1908,9 @@ COMPACT_RTF = NO
|
|||
|
||||
RTF_HYPERLINKS = NO
|
||||
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
|
||||
# file, i.e. a series of assignments. You only have to provide replacements,
|
||||
# missing definitions are set to their default value.
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's
|
||||
# configuration file, i.e. a series of assignments. You only have to provide
|
||||
# replacements, missing definitions are set to their default value.
|
||||
#
|
||||
# See also section "Doxygen usage" for information on how to generate the
|
||||
# default style sheet that doxygen normally uses.
|
||||
|
|
@ -1759,8 +1919,8 @@ RTF_HYPERLINKS = NO
|
|||
RTF_STYLESHEET_FILE =
|
||||
|
||||
# Set optional variables used in the generation of an RTF document. Syntax is
|
||||
# similar to doxygen's config file. A template extensions file can be generated
|
||||
# using doxygen -e rtf extensionFile.
|
||||
# similar to doxygen's configuration file. A template extensions file can be
|
||||
# generated using doxygen -e rtf extensionFile.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
|
@ -1846,6 +2006,13 @@ XML_OUTPUT = xml
|
|||
|
||||
XML_PROGRAMLISTING = NO
|
||||
|
||||
# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
|
||||
# namespace members in file scope as well, matching the HTML output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1878,9 +2045,9 @@ DOCBOOK_PROGRAMLISTING = NO
|
|||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
|
||||
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
|
||||
# structure of the code including all documentation. Note that this feature is
|
||||
# still experimental and incomplete at the moment.
|
||||
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
|
||||
# the structure of the code including all documentation. Note that this feature
|
||||
# is still experimental and incomplete at the moment.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
|
|
@ -2047,12 +2214,6 @@ EXTERNAL_GROUPS = YES
|
|||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -2066,15 +2227,6 @@ PERL_PATH = /usr/bin/perl
|
|||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
|
|
@ -2093,7 +2245,7 @@ HIDE_UNDOC_RELATIONS = YES
|
|||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# Bell Labs. The other options in this section have no effect if this option is
|
||||
# set to NO
|
||||
# The default value is: NO.
|
||||
# The default value is: YES.
|
||||
|
||||
HAVE_DOT = NO
|
||||
|
||||
|
|
@ -2207,7 +2359,8 @@ INCLUDED_BY_GRAPH = YES
|
|||
#
|
||||
# Note that enabling this option will significantly increase the time of a run.
|
||||
# So in most cases it will be better to enable call graphs for selected
|
||||
# functions only using the \callgraph command.
|
||||
# functions only using the \callgraph command. Disabling a call graph can be
|
||||
# accomplished by means of the command \hidecallgraph.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2218,7 +2371,8 @@ CALL_GRAPH = NO
|
|||
#
|
||||
# Note that enabling this option will significantly increase the time of a run.
|
||||
# So in most cases it will be better to enable caller graphs for selected
|
||||
# functions only using the \callergraph command.
|
||||
# functions only using the \callergraph command. Disabling a caller graph can be
|
||||
# accomplished by means of the command \hidecallergraph.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2241,11 +2395,17 @@ GRAPHICAL_HIERARCHY = YES
|
|||
DIRECTORY_GRAPH = YES
|
||||
|
||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot.
|
||||
# generated by dot. For an explanation of the image formats see the section
|
||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||
# http://www.graphviz.org/)).
|
||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||
# requirement).
|
||||
# Possible values are: png, jpg, gif and svg.
|
||||
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
|
||||
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
|
||||
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
|
||||
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
|
||||
# png:gdiplus:gdiplus.
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2296,6 +2456,11 @@ DIAFILE_DIRS =
|
|||
|
||||
PLANTUML_JAR_PATH =
|
||||
|
||||
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
|
||||
# configuration file for plantuml.
|
||||
|
||||
PLANTUML_CFG_FILE =
|
||||
|
||||
# When using plantuml, the specified paths are searched for files specified by
|
||||
# the !include statement in a plantuml block.
|
||||
|
||||
|
|
|
|||
222008
genesis.json
222008
genesis.json
File diff suppressed because it is too large
Load diff
|
|
@ -1,12 +1,10 @@
|
|||
add_subdirectory( fc )
|
||||
add_subdirectory( db )
|
||||
#add_subdirectory( deterministic_openssl_rand )
|
||||
add_subdirectory( app )
|
||||
add_subdirectory( chain )
|
||||
add_subdirectory( db )
|
||||
add_subdirectory( egenesis )
|
||||
add_subdirectory( fc )
|
||||
add_subdirectory( net )
|
||||
#add_subdirectory( p2p )
|
||||
add_subdirectory( plugins )
|
||||
add_subdirectory( time )
|
||||
add_subdirectory( utilities )
|
||||
add_subdirectory( app )
|
||||
add_subdirectory( plugins )
|
||||
add_subdirectory( wallet )
|
||||
|
|
|
|||
|
|
@ -4,16 +4,19 @@ file(GLOB EGENESIS_HEADERS "../egenesis/include/graphene/app/*.hpp")
|
|||
add_library( graphene_app
|
||||
api.cpp
|
||||
application.cpp
|
||||
config_util.cpp
|
||||
database_api.cpp
|
||||
plugin.cpp
|
||||
config_util.cpp
|
||||
${HEADERS}
|
||||
${EGENESIS_HEADERS}
|
||||
)
|
||||
|
||||
# need to link graphene_debug_witness because plugins aren't sufficiently isolated #246
|
||||
#target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
|
||||
target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_accounts_list graphene_affiliate_stats graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities graphene_debug_witness graphene_bookie graphene_elasticsearch peerplays_sidechain )
|
||||
target_link_libraries( graphene_app
|
||||
PUBLIC graphene_net graphene_utilities
|
||||
graphene_account_history graphene_accounts_list graphene_affiliate_stats graphene_bookie graphene_debug_witness graphene_elasticsearch graphene_es_objects graphene_generate_genesis graphene_market_history )
|
||||
|
||||
target_include_directories( graphene_app
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" )
|
||||
|
|
@ -30,3 +33,26 @@ INSTALL( TARGETS
|
|||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
INSTALL( FILES ${HEADERS} DESTINATION "include/graphene/app" )
|
||||
|
||||
|
||||
|
||||
add_library( graphene_plugin
|
||||
plugin.cpp
|
||||
|
||||
include/graphene/app/plugin.hpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_plugin
|
||||
PUBLIC graphene_net graphene_utilities )
|
||||
|
||||
target_include_directories( graphene_plugin
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
INSTALL( TARGETS
|
||||
graphene_app
|
||||
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ namespace graphene { namespace app {
|
|||
|
||||
vector<optional<signed_block>> block_api::get_blocks(uint32_t block_num_from, uint32_t block_num_to)const
|
||||
{
|
||||
FC_ASSERT( block_num_to >= block_num_from );
|
||||
FC_ASSERT( block_num_to >= block_num_from && block_num_to - block_num_from <= 100, "Total blocks to be returned should be less than 100");
|
||||
vector<optional<signed_block>> res;
|
||||
for(uint32_t block_num=block_num_from; block_num<=block_num_to; block_num++) {
|
||||
res.push_back(_db.fetch_block_by_number(block_num));
|
||||
|
|
@ -579,7 +579,10 @@ namespace graphene { namespace app {
|
|||
{
|
||||
FC_ASSERT( _app.chain_database() );
|
||||
const auto& db = *_app.chain_database();
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_get_account_history,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_account_history) );
|
||||
|
||||
vector<operation_history_object> result;
|
||||
account_id_type account;
|
||||
try {
|
||||
|
|
@ -627,13 +630,16 @@ namespace graphene { namespace app {
|
|||
{
|
||||
FC_ASSERT( _app.chain_database() );
|
||||
const auto& db = *_app.chain_database();
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_get_account_history_operations,
|
||||
"Number of querying history accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_account_history_operations) );
|
||||
|
||||
vector<operation_history_object> result;
|
||||
account_id_type account;
|
||||
try {
|
||||
account = database_api.get_account_id_from_string(account_id_or_name);
|
||||
} catch (...) { return result; }
|
||||
|
||||
|
||||
const auto& stats = account(db).statistics(db);
|
||||
if( stats.most_recent_op == account_transaction_history_id_type() ) return result;
|
||||
const account_transaction_history_object* node = &stats.most_recent_op(db);
|
||||
|
|
@ -667,7 +673,10 @@ namespace graphene { namespace app {
|
|||
{
|
||||
FC_ASSERT( _app.chain_database() );
|
||||
const auto& db = *_app.chain_database();
|
||||
FC_ASSERT(limit <= 100);
|
||||
FC_ASSERT( limit <= api_limit_get_relative_account_history,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_relative_account_history) );
|
||||
|
||||
vector<operation_history_object> result;
|
||||
account_id_type account;
|
||||
try {
|
||||
|
|
@ -797,14 +806,16 @@ namespace graphene { namespace app {
|
|||
}
|
||||
|
||||
// asset_api
|
||||
asset_api::asset_api(graphene::app::application& app) :
|
||||
asset_api::asset_api(graphene::app::application& app) :
|
||||
_app(app),
|
||||
_db( *app.chain_database()),
|
||||
database_api( std::ref(*app.chain_database())) { }
|
||||
asset_api::~asset_api() { }
|
||||
|
||||
vector<account_asset_balance> asset_api::get_asset_holders( std::string asset, uint32_t start, uint32_t limit ) const {
|
||||
FC_ASSERT(limit <= 100);
|
||||
FC_ASSERT( limit <= api_limit_get_asset_holders,
|
||||
"Number of querying asset holder accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_asset_holders) );
|
||||
|
||||
asset_id_type asset_id = database_api.get_asset_id_from_string( asset );
|
||||
const auto& bal_idx = _db.get_index_type< account_balance_index >().indices().get< by_asset_balance >();
|
||||
|
|
|
|||
|
|
@ -160,13 +160,12 @@ namespace detail {
|
|||
{
|
||||
// t.me/peerplays #seednodes
|
||||
vector<string> seeds = {
|
||||
"173.249.23.108:9777",
|
||||
"node.peerblock.trade:9777",
|
||||
"peerplays.blockoperations.com:9777",
|
||||
"pms.blockveritas.co:7777",
|
||||
"seed.ppy.alex-pu.info:8888",
|
||||
"seed.ppy.blckchnd.com:6116",
|
||||
"seed01.eifos.org:7777"
|
||||
"pts.blockveritas.co:6666",
|
||||
"seed-beatrice01.eifos.org:7777",
|
||||
"seed-testnet.ppy.alex-pu.info:7777",
|
||||
"seed.ppy-beatrice.blckchnd.com:6666",
|
||||
"seed.testnet.peerblock.trade:6666",
|
||||
"testnet-ppyapi.spacemx.tech:9777"
|
||||
};
|
||||
|
||||
for( const string& endpoint_string : seeds )
|
||||
|
|
@ -381,7 +380,6 @@ namespace detail {
|
|||
_chain_db->enable_standby_votes_tracking( _options->at("enable-standby-votes-tracking").as<bool>() );
|
||||
}
|
||||
|
||||
bool replay = false;
|
||||
std::string replay_reason = "reason not provided";
|
||||
|
||||
if( _options->count("replay-blockchain") )
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
optional<block_header> get_block_header(uint32_t block_num)const;
|
||||
map<uint32_t, optional<block_header>> get_block_header_batch(const vector<uint32_t> block_nums)const;
|
||||
optional<signed_block> get_block(uint32_t block_num)const;
|
||||
vector<optional<signed_block>> get_blocks(uint32_t block_num_from, uint32_t block_num_to)const;
|
||||
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;
|
||||
|
||||
// Globals
|
||||
|
|
@ -234,6 +235,17 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
vector<offer_history_object> get_offer_history_by_item(const offer_history_id_type lower_id, const nft_id_type item, uint32_t limit) const;
|
||||
vector<offer_history_object> get_offer_history_by_bidder(const offer_history_id_type lower_id, const account_id_type bidder_account_id, uint32_t limit) const;
|
||||
|
||||
uint32_t api_limit_get_lower_bound_symbol = 100;
|
||||
uint32_t api_limit_get_limit_orders = 300;
|
||||
uint32_t api_limit_get_limit_orders_by_account = 101;
|
||||
uint32_t api_limit_get_order_book = 50;
|
||||
uint32_t api_limit_all_offers_count = 100;
|
||||
uint32_t api_limit_lookup_accounts = 1000;
|
||||
uint32_t api_limit_lookup_witness_accounts = 1000;
|
||||
uint32_t api_limit_lookup_committee_member_accounts = 1000;
|
||||
uint32_t api_limit_get_trade_history = 100;
|
||||
uint32_t api_limit_get_trade_history_by_sequence = 100;
|
||||
|
||||
// Account Role
|
||||
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
|
||||
|
||||
|
|
@ -485,6 +497,21 @@ optional<signed_block> database_api_impl::get_block(uint32_t block_num)const
|
|||
return _db.fetch_block_by_number(block_num);
|
||||
}
|
||||
|
||||
vector<optional<signed_block>> database_api::get_blocks(uint32_t block_num_from, uint32_t block_num_to)const
|
||||
{
|
||||
return my->get_blocks( block_num_from, block_num_to );
|
||||
}
|
||||
|
||||
vector<optional<signed_block>> database_api_impl::get_blocks(uint32_t block_num_from, uint32_t block_num_to)const
|
||||
{
|
||||
FC_ASSERT( block_num_to >= block_num_from && block_num_to - block_num_from <= 100, "Total blocks to be returned should be less than 100");
|
||||
vector<optional<signed_block>> res;
|
||||
for(uint32_t block_num=block_num_from; block_num<=block_num_to; block_num++) {
|
||||
res.push_back(_db.fetch_block_by_number(block_num));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
processed_transaction database_api::get_transaction( uint32_t block_num, uint32_t trx_in_block )const
|
||||
{
|
||||
return my->get_transaction( block_num, trx_in_block );
|
||||
|
|
@ -877,7 +904,9 @@ map<string,account_id_type> database_api::lookup_accounts(const string& lower_bo
|
|||
|
||||
map<string,account_id_type> database_api_impl::lookup_accounts(const string& lower_bound_name, uint32_t limit)const
|
||||
{
|
||||
FC_ASSERT( limit <= 1000 );
|
||||
FC_ASSERT( limit <= api_limit_lookup_accounts,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_lookup_accounts) );
|
||||
const auto& accounts_by_name = _db.get_index_type<account_index>().indices().get<by_name>();
|
||||
map<string,account_id_type> result;
|
||||
|
||||
|
|
@ -914,7 +943,7 @@ vector<asset> database_api::get_account_balances(const std::string& account_name
|
|||
return my->get_account_balances( account_name_or_id, assets );
|
||||
}
|
||||
|
||||
vector<asset> database_api_impl::get_account_balances( const std::string& account_name_or_id,
|
||||
vector<asset> database_api_impl::get_account_balances( const std::string& account_name_or_id,
|
||||
const flat_set<asset_id_type>& assets)const
|
||||
{
|
||||
const account_object* account = get_account_from_string(account_name_or_id);
|
||||
|
|
@ -1085,7 +1114,9 @@ vector<asset_object> database_api::list_assets(const string& lower_bound_symbol,
|
|||
|
||||
vector<asset_object> database_api_impl::list_assets(const string& lower_bound_symbol, uint32_t limit)const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_get_lower_bound_symbol,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_lower_bound_symbol) );
|
||||
const auto& assets_by_symbol = _db.get_index_type<asset_index>().indices().get<by_symbol>();
|
||||
vector<asset_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -1535,7 +1566,9 @@ order_book database_api::get_order_book( const string& base, const string& quote
|
|||
order_book database_api_impl::get_order_book( const string& base, const string& quote, unsigned limit )const
|
||||
{
|
||||
using boost::multiprecision::uint128_t;
|
||||
FC_ASSERT( limit <= 50 );
|
||||
FC_ASSERT( limit <= api_limit_get_order_book,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_order_book) );
|
||||
|
||||
order_book result;
|
||||
result.base = base;
|
||||
|
|
@ -1597,7 +1630,9 @@ vector<market_trade> database_api_impl::get_trade_history( const string& base,
|
|||
fc::time_point_sec stop,
|
||||
unsigned limit )const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_get_trade_history,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_get_trade_history) );
|
||||
|
||||
auto assets = lookup_asset_symbols( {base, quote} );
|
||||
FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) );
|
||||
|
|
@ -1716,7 +1751,9 @@ map<string, witness_id_type> database_api::lookup_witness_accounts(const string&
|
|||
|
||||
map<string, witness_id_type> database_api_impl::lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const
|
||||
{
|
||||
FC_ASSERT( limit <= 1000 );
|
||||
FC_ASSERT( limit <= api_limit_lookup_witness_accounts,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_lookup_witness_accounts) );
|
||||
const auto& witnesses_by_id = _db.get_index_type<witness_index>().indices().get<by_id>();
|
||||
|
||||
// we want to order witnesses by account name, but that name is in the account object
|
||||
|
|
@ -1792,7 +1829,9 @@ map<string, committee_member_id_type> database_api::lookup_committee_member_acco
|
|||
|
||||
map<string, committee_member_id_type> database_api_impl::lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const
|
||||
{
|
||||
FC_ASSERT( limit <= 1000 );
|
||||
FC_ASSERT( limit <= api_limit_lookup_committee_member_accounts,
|
||||
"Number of querying accounts can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_lookup_committee_member_accounts) );
|
||||
const auto& committee_members_by_id = _db.get_index_type<committee_member_index>().indices().get<by_id>();
|
||||
|
||||
// we want to order committee_members by account name, but that name is in the account object
|
||||
|
|
@ -2546,18 +2585,8 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type
|
|||
|
||||
share_type total_amount;
|
||||
auto balance_type = vesting_balance_type::gpos;
|
||||
#ifdef USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX
|
||||
// get only once a collection of accounts that hold nonzero vesting balances of the dividend asset
|
||||
auto vesting_balances_begin =
|
||||
vesting_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(asset_id_type(), balance_type));
|
||||
auto vesting_balances_end =
|
||||
vesting_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(asset_id_type(), balance_type, share_type()));
|
||||
|
||||
for (const vesting_balance_object& vesting_balance_obj : boost::make_iterator_range(vesting_balances_begin, vesting_balances_end))
|
||||
{
|
||||
total_amount += vesting_balance_obj.balance.amount;
|
||||
}
|
||||
#else
|
||||
// get only once a collection of accounts that hold nonzero vesting balances of the dividend asset
|
||||
const vesting_balance_index& vesting_index = _db.get_index_type<vesting_balance_index>();
|
||||
const auto& vesting_balances = vesting_index.indices().get<by_id>();
|
||||
for (const vesting_balance_object& vesting_balance_obj : vesting_balances)
|
||||
|
|
@ -2567,7 +2596,6 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type
|
|||
total_amount += vesting_balance_obj.balance.amount;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vector<vesting_balance_object> account_vbos;
|
||||
const time_point_sec now = _db.head_block_time();
|
||||
|
|
@ -2578,9 +2606,9 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type
|
|||
&& balance.balance.asset_id == asset_id_type())
|
||||
account_vbos.emplace_back(balance);
|
||||
});
|
||||
|
||||
|
||||
share_type allowed_withdraw_amount = 0, account_vested_balance = 0;
|
||||
|
||||
|
||||
for (const vesting_balance_object& vesting_balance_obj : account_vbos)
|
||||
{
|
||||
account_vested_balance += vesting_balance_obj.balance.amount;
|
||||
|
|
@ -2912,7 +2940,9 @@ vector<offer_object> database_api::list_offers(const offer_id_type lower_id, uin
|
|||
|
||||
vector<offer_object> database_api_impl::list_offers(const offer_id_type lower_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& offers_idx = _db.get_index_type<offer_index>().indices().get<by_id>();
|
||||
vector<offer_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -2932,7 +2962,9 @@ vector<offer_object> database_api::list_sell_offers(const offer_id_type lower_id
|
|||
|
||||
vector<offer_object> database_api_impl::list_sell_offers(const offer_id_type lower_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& offers_idx = _db.get_index_type<offer_index>().indices().get<by_id>();
|
||||
vector<offer_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -2958,7 +2990,9 @@ vector<offer_object> database_api::list_buy_offers(const offer_id_type lower_id,
|
|||
|
||||
vector<offer_object> database_api_impl::list_buy_offers(const offer_id_type lower_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& offers_idx = _db.get_index_type<offer_index>().indices().get<by_id>();
|
||||
vector<offer_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -2985,7 +3019,9 @@ vector<offer_history_object> database_api::list_offer_history(const offer_histor
|
|||
|
||||
vector<offer_history_object> database_api_impl::list_offer_history(const offer_history_id_type lower_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& oh_idx = _db.get_index_type<offer_history_index>().indices().get<by_id>();
|
||||
vector<offer_history_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -3005,7 +3041,9 @@ vector<offer_object> database_api::get_offers_by_issuer(const offer_id_type lowe
|
|||
|
||||
vector<offer_object> database_api_impl::get_offers_by_issuer(const offer_id_type lower_id, const account_id_type issuer_account_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& offers_idx = _db.get_index_type<offer_index>().indices().get<by_id>();
|
||||
vector<offer_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -3029,7 +3067,9 @@ vector<offer_object> database_api::get_offers_by_item(const offer_id_type lower_
|
|||
|
||||
vector<offer_object> database_api_impl::get_offers_by_item(const offer_id_type lower_id, const nft_id_type item, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& offers_idx = _db.get_index_type<offer_index>().indices().get<by_id>();
|
||||
vector<offer_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -3064,7 +3104,9 @@ vector<offer_history_object> database_api::get_offer_history_by_bidder(const off
|
|||
|
||||
vector<offer_history_object> database_api_impl::get_offer_history_by_issuer(const offer_history_id_type lower_id, const account_id_type issuer_account_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& oh_idx = _db.get_index_type<offer_history_index>().indices().get<by_id>();
|
||||
vector<offer_history_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -3085,7 +3127,9 @@ vector<offer_history_object> database_api_impl::get_offer_history_by_issuer(cons
|
|||
|
||||
vector<offer_history_object> database_api_impl::get_offer_history_by_item(const offer_history_id_type lower_id, const nft_id_type item, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& oh_idx = _db.get_index_type<offer_history_index>().indices().get<by_id>();
|
||||
vector<offer_history_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -3107,7 +3151,9 @@ vector<offer_history_object> database_api_impl::get_offer_history_by_item(const
|
|||
|
||||
vector<offer_history_object> database_api_impl::get_offer_history_by_bidder(const offer_history_id_type lower_id, const account_id_type bidder_account_id, uint32_t limit) const
|
||||
{
|
||||
FC_ASSERT( limit <= 100 );
|
||||
FC_ASSERT( limit <= api_limit_all_offers_count,
|
||||
"Number of querying offers can not be greater than ${configured_limit}",
|
||||
("configured_limit", api_limit_all_offers_count) );
|
||||
const auto& oh_idx = _db.get_index_type<offer_history_index>().indices().get<by_id>();
|
||||
vector<offer_history_object> result;
|
||||
result.reserve(limit);
|
||||
|
|
@ -3143,6 +3189,7 @@ vector<account_role_object> database_api_impl::get_account_roles_by_owner(accoun
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Private methods //
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ namespace graphene { namespace app {
|
|||
fc::time_point_sec start, fc::time_point_sec end )const;
|
||||
vector<account_balance_object> list_core_accounts()const;
|
||||
flat_set<uint32_t> get_market_history_buckets()const;
|
||||
uint32_t api_limit_get_account_history_operations = 100;
|
||||
uint32_t api_limit_get_account_history = 100;
|
||||
uint32_t api_limit_get_relative_account_history = 100;
|
||||
private:
|
||||
application& _app;
|
||||
graphene::app::database_api database_api;
|
||||
|
|
@ -354,6 +357,7 @@ namespace graphene { namespace app {
|
|||
*/
|
||||
vector<asset_holders> get_all_asset_holders() const;
|
||||
|
||||
uint32_t api_limit_get_asset_holders = 100;
|
||||
private:
|
||||
graphene::app::application& _app;
|
||||
graphene::chain::database& _db;
|
||||
|
|
|
|||
|
|
@ -199,6 +199,14 @@ class database_api
|
|||
*/
|
||||
optional<signed_block> get_block(uint32_t block_num)const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve a list of signed blocks
|
||||
* @param block_num_from start
|
||||
* @param block_num_to end
|
||||
* @return list of referenced blocks
|
||||
*/
|
||||
vector<optional<signed_block>> get_blocks(uint32_t block_num_from, uint32_t block_num_to)const;
|
||||
|
||||
/**
|
||||
* @brief used to fetch an individual transaction.
|
||||
*/
|
||||
|
|
@ -934,7 +942,8 @@ class database_api
|
|||
// ACCOUNT ROLE //
|
||||
//////////////////
|
||||
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
|
||||
private:
|
||||
|
||||
private:
|
||||
std::shared_ptr< database_api_impl > my;
|
||||
};
|
||||
|
||||
|
|
@ -964,6 +973,7 @@ FC_API(graphene::app::database_api,
|
|||
(get_block_header)
|
||||
(get_block_header_batch)
|
||||
(get_block)
|
||||
(get_blocks)
|
||||
(get_transaction)
|
||||
(get_recent_transaction_by_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,143 +8,29 @@ add_dependencies( build_hardfork_hpp cat-parts )
|
|||
file(GLOB HEADERS "include/graphene/chain/*.hpp")
|
||||
file(GLOB PROTOCOL_HEADERS "include/graphene/chain/protocol/*.hpp")
|
||||
|
||||
if( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||
set( GRAPHENE_DB_FILES
|
||||
db_balance.cpp
|
||||
db_bet.cpp
|
||||
db_block.cpp
|
||||
db_debug.cpp
|
||||
db_getter.cpp
|
||||
db_init.cpp
|
||||
db_maint.cpp
|
||||
db_management.cpp
|
||||
db_market.cpp
|
||||
db_update.cpp
|
||||
db_witness_schedule.cpp
|
||||
)
|
||||
file(GLOB CPP_FILES "*.cpp")
|
||||
file(GLOB PROTOCOL_CPP_FILES "protocol/*.cpp")
|
||||
|
||||
#if( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||
list(FILTER CPP_FILES EXCLUDE REGEX "[/]database[.]cpp$")
|
||||
#message ("--- ${CPP_FILES}")
|
||||
message( STATUS "Graphene database unity build disabled" )
|
||||
else( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||
set( GRAPHENE_DB_FILES
|
||||
database.cpp )
|
||||
message( STATUS "Graphene database unity build enabled" )
|
||||
endif( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||
#else( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||
# list(FILTER CPP_FILES EXCLUDE REGEX ".*db_.*[.]cpp$")
|
||||
# #message ("--- ${CPP_FILES}")
|
||||
# message( STATUS "Graphene database unity build enabled" )
|
||||
#endif( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||
|
||||
## SORT .cpp by most likely to change / break compile
|
||||
add_library( graphene_chain
|
||||
|
||||
# As database takes the longest to compile, start it first
|
||||
${GRAPHENE_DB_FILES}
|
||||
fork_database.cpp
|
||||
|
||||
protocol/types.cpp
|
||||
protocol/address.cpp
|
||||
protocol/authority.cpp
|
||||
protocol/asset.cpp
|
||||
protocol/assert.cpp
|
||||
protocol/account.cpp
|
||||
protocol/transfer.cpp
|
||||
protocol/chain_parameters.cpp
|
||||
protocol/committee_member.cpp
|
||||
protocol/witness.cpp
|
||||
protocol/market.cpp
|
||||
protocol/proposal.cpp
|
||||
protocol/withdraw_permission.cpp
|
||||
protocol/asset_ops.cpp
|
||||
protocol/lottery_ops.cpp
|
||||
protocol/memo.cpp
|
||||
protocol/worker.cpp
|
||||
protocol/custom.cpp
|
||||
protocol/operations.cpp
|
||||
protocol/transaction.cpp
|
||||
protocol/block.cpp
|
||||
protocol/fee_schedule.cpp
|
||||
protocol/confidential.cpp
|
||||
protocol/vote.cpp
|
||||
protocol/tournament.cpp
|
||||
protocol/small_ops.cpp
|
||||
protocol/custom_permission.cpp
|
||||
protocol/custom_account_authority.cpp
|
||||
protocol/offer.cpp
|
||||
|
||||
genesis_state.cpp
|
||||
get_config.cpp
|
||||
|
||||
pts_address.cpp
|
||||
|
||||
evaluator.cpp
|
||||
balance_evaluator.cpp
|
||||
account_evaluator.cpp
|
||||
assert_evaluator.cpp
|
||||
witness_evaluator.cpp
|
||||
committee_member_evaluator.cpp
|
||||
asset_evaluator.cpp
|
||||
lottery_evaluator.cpp
|
||||
transfer_evaluator.cpp
|
||||
proposal_evaluator.cpp
|
||||
market_evaluator.cpp
|
||||
vesting_balance_evaluator.cpp
|
||||
tournament_evaluator.cpp
|
||||
tournament_object.cpp
|
||||
match_object.cpp
|
||||
game_object.cpp
|
||||
withdraw_permission_evaluator.cpp
|
||||
worker_evaluator.cpp
|
||||
confidential_evaluator.cpp
|
||||
special_authority.cpp
|
||||
buyback.cpp
|
||||
|
||||
account_object.cpp
|
||||
asset_object.cpp
|
||||
fba_object.cpp
|
||||
proposal_object.cpp
|
||||
vesting_balance_object.cpp
|
||||
small_objects.cpp
|
||||
|
||||
block_database.cpp
|
||||
|
||||
is_authorized_asset.cpp
|
||||
|
||||
protocol/sport.cpp
|
||||
sport_evaluator.cpp
|
||||
protocol/event_group.cpp
|
||||
event_group_evaluator.cpp
|
||||
event_group_object.cpp
|
||||
protocol/event.cpp
|
||||
event_evaluator.cpp
|
||||
event_object.cpp
|
||||
protocol/betting_market.cpp
|
||||
betting_market_evaluator.cpp
|
||||
betting_market_object.cpp
|
||||
betting_market_group_object.cpp
|
||||
custom_permission_evaluator.cpp
|
||||
custom_account_authority_evaluator.cpp
|
||||
|
||||
affiliate_payout.cpp
|
||||
|
||||
offer_object.cpp
|
||||
offer_evaluator.cpp
|
||||
nft_evaluator.cpp
|
||||
protocol/nft.cpp
|
||||
protocol/account_role.cpp
|
||||
account_role_evaluator.cpp
|
||||
|
||||
son_evaluator.cpp
|
||||
son_object.cpp
|
||||
|
||||
son_wallet_evaluator.cpp
|
||||
son_wallet_deposit_evaluator.cpp
|
||||
son_wallet_withdraw_evaluator.cpp
|
||||
|
||||
sidechain_address_evaluator.cpp
|
||||
sidechain_transaction_evaluator.cpp
|
||||
|
||||
${CPP_FILES}
|
||||
${PROTOCOL_CPP_FILES}
|
||||
${HEADERS}
|
||||
${PROTOCOL_HEADERS}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
|
||||
)
|
||||
|
||||
add_dependencies( graphene_chain build_hardfork_hpp )
|
||||
target_link_libraries( graphene_chain fc graphene_db )
|
||||
target_link_libraries( graphene_chain graphene_db )
|
||||
target_include_directories( graphene_chain
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -596,7 +596,6 @@ void_result asset_update_dividend_evaluator::do_apply( const asset_update_divide
|
|||
obj.referrer = op.issuer;
|
||||
obj.lifetime_referrer = op.issuer(db()).lifetime_referrer;
|
||||
|
||||
auto& params = db().get_global_properties().parameters;
|
||||
obj.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
||||
obj.lifetime_referrer_fee_percentage = GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE;
|
||||
obj.referrer_rewards_percentage = GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE;
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
|
|||
*t += percents_to_distribute / holders.size();
|
||||
}
|
||||
auto sweeps_distribution_percentage = db.get_global_properties().parameters.sweeps_distribution_percentage();
|
||||
for( int c = 0; c < winner_numbers.size(); ++c ) {
|
||||
for( size_t c = 0; c < winner_numbers.size(); ++c ) {
|
||||
auto winner_num = winner_numbers[c];
|
||||
lottery_reward_operation reward_op;
|
||||
reward_op.lottery = get_id();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@
|
|||
#include "db_maint.cpp"
|
||||
#include "db_management.cpp"
|
||||
#include "db_market.cpp"
|
||||
#include "db_notify.cpp"
|
||||
#include "db_update.cpp"
|
||||
#include "db_witness_schedule.cpp"
|
||||
#include "db_notify.cpp"
|
||||
|
|
@ -140,8 +140,10 @@ void database::adjust_sweeps_vesting_balance(account_id_type account, int64_t de
|
|||
b.balance = delta;
|
||||
});
|
||||
} else {
|
||||
if( delta < 0 )
|
||||
FC_ASSERT( itr->get_balance() >= -delta, "Insufficient Balance: ${a}'s balance of ${b} is less than required ${r}", ("a",account)("b",itr->get_balance())("r",-delta));
|
||||
if( delta < 0 ) {
|
||||
uint64_t delta_uint64 = -delta;
|
||||
FC_ASSERT( itr->get_balance() >= delta_uint64, "Insufficient Balance: ${a}'s balance of ${b} is less than required ${r}", ("a",account)("b",itr->get_balance())("r",-delta));
|
||||
}
|
||||
modify(*itr, [&delta,&asset_id,this](sweeps_vesting_balance_object& b) {
|
||||
b.adjust_balance( asset( delta, asset_id ) );
|
||||
b.last_claim_date = head_block_time();
|
||||
|
|
|
|||
|
|
@ -303,8 +303,6 @@ void database::settle_betting_market_group(const betting_market_group_object& be
|
|||
remove(betting_market);
|
||||
}
|
||||
|
||||
const event_object& event = betting_market_group.event_id(*this);
|
||||
|
||||
fc_dlog(fc::logger::get("betting"), "removing betting market group ${id}", ("id", betting_market_group.id));
|
||||
remove(betting_market_group);
|
||||
|
||||
|
|
@ -537,11 +535,9 @@ int match_bet(database& db, const bet_object& taker_bet, const bet_object& maker
|
|||
// because we matched at the maker's odds and not the taker's odds, the remaining amount to match
|
||||
// may not be an even multiple of the taker's odds; round it down.
|
||||
share_type taker_remaining_factor = unrounded_taker_remaining_amount_to_match / takers_odds_maker_odds_ratio;
|
||||
share_type taker_remaining_maker_amount_to_match = taker_remaining_factor * takers_odds_maker_odds_ratio;
|
||||
share_type taker_remaining_bet_amount = taker_remaining_factor * takers_odds_taker_odds_ratio;
|
||||
|
||||
taker_refund_amount = taker_bet.amount_to_bet.amount - taker_amount_to_match - taker_remaining_bet_amount;
|
||||
//idump((taker_remaining_factor)(taker_remaining_maker_amount_to_match)(taker_remaining_bet_amount)(taker_refund_amount));
|
||||
}
|
||||
|
||||
if (taker_refund_amount > share_type())
|
||||
|
|
|
|||
|
|
@ -715,7 +715,8 @@ void database::_apply_block( const signed_block& next_block )
|
|||
perform_chain_maintenance(next_block, global_props);
|
||||
|
||||
check_ending_lotteries();
|
||||
|
||||
check_ending_nft_lotteries();
|
||||
|
||||
create_block_summary(next_block);
|
||||
place_delayed_bets(); // must happen after update_global_dynamic_data() updates the time
|
||||
clear_expired_transactions();
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ uint32_t database::last_non_undoable_block_num() const
|
|||
return head_block_num() - _undo_db.size();
|
||||
}
|
||||
|
||||
std::vector<uint32_t> database::get_seeds(asset_id_type for_asset, uint8_t count_winners) const
|
||||
std::vector<uint32_t> database::get_seeds( asset_id_type for_asset, uint8_t count_winners ) const
|
||||
{
|
||||
FC_ASSERT( count_winners <= 64 );
|
||||
std::string salted_string = std::string(_random_number_generator._seed) + std::to_string(for_asset.instance.value);
|
||||
|
|
@ -315,4 +315,36 @@ bool database::is_son_active( son_id_type son_id )
|
|||
return (it_son != active_son_ids.end());
|
||||
}
|
||||
|
||||
vector<uint64_t> database::get_random_numbers(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates)
|
||||
{
|
||||
FC_ASSERT( selections <= 100000 );
|
||||
if (duplicates == false) {
|
||||
FC_ASSERT( maximum - minimum >= selections );
|
||||
}
|
||||
|
||||
vector<uint64_t> v;
|
||||
v.reserve(selections);
|
||||
|
||||
if (duplicates) {
|
||||
for (uint64_t i = 0; i < selections; i++) {
|
||||
int64_t rnd = get_random_bits(maximum - minimum) + minimum;
|
||||
v.push_back(rnd);
|
||||
}
|
||||
} else {
|
||||
vector<uint64_t> tmpv;
|
||||
tmpv.reserve(selections);
|
||||
for (uint64_t i = minimum; i < maximum; i++) {
|
||||
tmpv.push_back(i);
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; (i < selections) && (tmpv.size() > 0); i++) {
|
||||
uint64_t idx = get_random_bits(tmpv.size());
|
||||
v.push_back(tmpv.at(idx));
|
||||
tmpv.erase(tmpv.begin() + idx);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||
#include <graphene/chain/offer_object.hpp>
|
||||
#include <graphene/chain/account_role_object.hpp>
|
||||
#include <graphene/chain/random_number_object.hpp>
|
||||
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
|
||||
|
|
@ -94,12 +95,14 @@
|
|||
#include <graphene/chain/offer_evaluator.hpp>
|
||||
#include <graphene/chain/nft_evaluator.hpp>
|
||||
#include <graphene/chain/account_role_evaluator.hpp>
|
||||
#include <graphene/chain/nft_lottery_evaluator.hpp>
|
||||
#include <graphene/chain/son_evaluator.hpp>
|
||||
#include <graphene/chain/son_wallet_evaluator.hpp>
|
||||
#include <graphene/chain/son_wallet_deposit_evaluator.hpp>
|
||||
#include <graphene/chain/son_wallet_withdraw_evaluator.hpp>
|
||||
#include <graphene/chain/sidechain_address_evaluator.hpp>
|
||||
#include <graphene/chain/sidechain_transaction_evaluator.hpp>
|
||||
#include <graphene/chain/random_number_evaluator.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
|
|
@ -203,6 +206,12 @@ const uint8_t offer_history_object::type_id;
|
|||
const uint8_t account_role_object::space_id;
|
||||
const uint8_t account_role_object::type_id;
|
||||
|
||||
const uint8_t nft_lottery_balance_object::space_id;
|
||||
const uint8_t nft_lottery_balance_object::type_id;
|
||||
|
||||
const uint8_t random_number_object::space_id;
|
||||
const uint8_t random_number_object::type_id;
|
||||
|
||||
void database::initialize_evaluators()
|
||||
{
|
||||
_operation_evaluators.resize(255);
|
||||
|
|
@ -295,6 +304,9 @@ void database::initialize_evaluators()
|
|||
register_evaluator<account_role_create_evaluator>();
|
||||
register_evaluator<account_role_update_evaluator>();
|
||||
register_evaluator<account_role_delete_evaluator>();
|
||||
register_evaluator<nft_lottery_token_purchase_evaluator>();
|
||||
register_evaluator<nft_lottery_reward_evaluator>();
|
||||
register_evaluator<nft_lottery_end_evaluator>();
|
||||
register_evaluator<create_son_evaluator>();
|
||||
register_evaluator<update_son_evaluator>();
|
||||
register_evaluator<deregister_son_evaluator>();
|
||||
|
|
@ -314,6 +326,7 @@ void database::initialize_evaluators()
|
|||
register_evaluator<sidechain_transaction_sign_evaluator>();
|
||||
register_evaluator<sidechain_transaction_send_evaluator>();
|
||||
register_evaluator<sidechain_transaction_settle_evaluator>();
|
||||
register_evaluator<random_number_store_evaluator>();
|
||||
}
|
||||
|
||||
void database::initialize_indexes()
|
||||
|
|
@ -403,7 +416,9 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<lottery_balance_index > >();
|
||||
add_index< primary_index<sweeps_vesting_balance_index > >();
|
||||
add_index< primary_index<offer_history_index > >();
|
||||
add_index< primary_index<nft_lottery_balance_index > >();
|
||||
add_index< primary_index<son_stats_index > >();
|
||||
add_index< primary_index<random_number_index > >();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -933,7 +948,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
|
||||
const auto& idx = get_index_type<asset_index>().indices().get<by_symbol>();
|
||||
auto it = idx.begin();
|
||||
bool has_imbalanced_assets = false;
|
||||
|
||||
while( it != idx.end() )
|
||||
{
|
||||
|
|
@ -945,7 +959,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
FC_ASSERT( debt_itr != total_debts.end() );
|
||||
if( supply_itr->second != debt_itr->second )
|
||||
{
|
||||
has_imbalanced_assets = true;
|
||||
elog( "Genesis for asset ${aname} is not balanced\n"
|
||||
" Debt is ${debt}\n"
|
||||
" Supply is ${supply}\n",
|
||||
|
|
@ -957,10 +970,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
}
|
||||
++it;
|
||||
}
|
||||
// @romek
|
||||
#if 0
|
||||
FC_ASSERT( !has_imbalanced_assets );
|
||||
#endif
|
||||
|
||||
// Save tallied supplies
|
||||
for( const auto& item : total_supplies )
|
||||
|
|
|
|||
|
|
@ -32,24 +32,24 @@
|
|||
#include <graphene/chain/is_authorized_asset.hpp>
|
||||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/account_role_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/budget_record_object.hpp>
|
||||
#include <graphene/chain/buyback_object.hpp>
|
||||
#include <graphene/chain/chain_property_object.hpp>
|
||||
#include <graphene/chain/committee_member_object.hpp>
|
||||
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||
#include <graphene/chain/fba_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/market_object.hpp>
|
||||
#include <graphene/chain/special_authority_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/vote_count.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/witness_schedule_object.hpp>
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||
|
||||
#define USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX // vesting_balance_object by_asset_balance index needed
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -178,36 +178,52 @@ void database::update_worker_votes()
|
|||
|
||||
void database::pay_sons()
|
||||
{
|
||||
auto get_weight = []( uint64_t total_votes ) {
|
||||
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0);
|
||||
uint16_t weight = std::max((total_votes >> bits_to_drop), uint64_t(1) );
|
||||
return weight;
|
||||
};
|
||||
time_point_sec now = head_block_time();
|
||||
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
|
||||
// Current requirement is that we have to pay every 24 hours, so the following check
|
||||
if( dpo.son_budget.value > 0 && ((now - dpo.last_son_payout_time) >= fc::seconds(get_global_properties().parameters.son_pay_time()))) {
|
||||
auto sons = sort_votable_objects<son_index>(get_global_properties().parameters.maximum_son_count());
|
||||
// After SON2 HF
|
||||
uint64_t total_votes = 0;
|
||||
for( const son_object& son : sons )
|
||||
{
|
||||
total_votes += _vote_tally_buffer[son.vote_id];
|
||||
}
|
||||
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0);
|
||||
auto get_weight = [&bits_to_drop]( uint64_t son_votes ) {
|
||||
uint16_t weight = std::max((son_votes >> bits_to_drop), uint64_t(1) );
|
||||
return weight;
|
||||
};
|
||||
// Before SON2 HF
|
||||
auto get_weight_before_son2_hf = []( uint64_t son_votes ) {
|
||||
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(son_votes)) - 15, 0);
|
||||
uint16_t weight = std::max((son_votes >> bits_to_drop), uint64_t(1) );
|
||||
return weight;
|
||||
};
|
||||
uint64_t weighted_total_txs_signed = 0;
|
||||
share_type son_budget = dpo.son_budget;
|
||||
get_index_type<son_stats_index>().inspect_all_objects([this, &weighted_total_txs_signed, &get_weight](const object& o) {
|
||||
get_index_type<son_stats_index>().inspect_all_objects([this, &weighted_total_txs_signed, &get_weight, &now, &get_weight_before_son2_hf](const object& o) {
|
||||
const son_statistics_object& s = static_cast<const son_statistics_object&>(o);
|
||||
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]);
|
||||
}
|
||||
weighted_total_txs_signed += (s.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](const object& o) {
|
||||
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){
|
||||
auto son_params = get_global_properties().parameters;
|
||||
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;
|
||||
|
||||
modify( *son_obj, [&]( son_object& _son_obj)
|
||||
{
|
||||
_son_obj.pay_son_fee(pay, *this);
|
||||
|
|
@ -1190,7 +1206,6 @@ uint32_t database::get_gpos_current_subperiod()
|
|||
const auto period_start = fc::time_point_sec(gpo.parameters.gpos_period_start());
|
||||
|
||||
// variables needed
|
||||
const fc::time_point_sec period_end = period_start + vesting_period;
|
||||
const auto number_of_subperiods = vesting_period / vesting_subperiod;
|
||||
const auto now = this->head_block_time();
|
||||
auto seconds_since_period_start = now.sec_since_epoch() - period_start.sec_since_epoch();
|
||||
|
|
@ -1383,7 +1398,6 @@ void schedule_pending_dividend_balances(database& db,
|
|||
|
||||
uint32_t holder_account_count = 0;
|
||||
|
||||
#ifdef USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX
|
||||
// get only once a collection of accounts that hold nonzero vesting balances of the dividend asset
|
||||
auto vesting_balances_begin =
|
||||
vesting_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(dividend_holder_asset_obj.id, balance_type));
|
||||
|
|
@ -1398,22 +1412,6 @@ void schedule_pending_dividend_balances(database& db,
|
|||
("owner", vesting_balance_obj.owner(db).name)
|
||||
("amount", vesting_balance_obj.balance.amount));
|
||||
}
|
||||
#else
|
||||
// get only once a collection of accounts that hold nonzero vesting balances of the dividend asset
|
||||
const auto& vesting_balances = vesting_index.indices().get<by_id>();
|
||||
for (const vesting_balance_object& vesting_balance_obj : vesting_balances)
|
||||
{
|
||||
if (vesting_balance_obj.balance.asset_id == dividend_holder_asset_obj.id && vesting_balance_obj.balance.amount &&
|
||||
vesting_balance_object.balance_type == balance_type)
|
||||
{
|
||||
vesting_amounts[vesting_balance_obj.owner] += vesting_balance_obj.balance.amount;
|
||||
++gpos_holder_account_count;
|
||||
dlog("Vesting balance for account: ${owner}, amount: ${amount}",
|
||||
("owner", vesting_balance_obj.owner(db).name)
|
||||
("amount", vesting_balance_obj.balance.amount));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto current_distribution_account_balance_iter = current_distribution_account_balance_range.begin();
|
||||
if(db.head_block_time() < HARDFORK_GPOS_TIME)
|
||||
|
|
@ -1867,7 +1865,6 @@ void process_dividend_assets(database& db)
|
|||
{
|
||||
// if there was a previous payout, make our next payment one interval
|
||||
uint32_t current_time_sec = current_head_block_time.sec_since_epoch();
|
||||
fc::time_point_sec reference_time = *dividend_data_obj.last_scheduled_payout_time;
|
||||
uint32_t next_possible_time_sec = dividend_data_obj.last_scheduled_payout_time->sec_since_epoch();
|
||||
do
|
||||
next_possible_time_sec += *dividend_data_obj.options.payout_interval;
|
||||
|
|
@ -1958,6 +1955,21 @@ void database::perform_son_tasks()
|
|||
}
|
||||
}
|
||||
|
||||
void update_son_asset(database& db)
|
||||
{
|
||||
if( db.head_block_time() >= HARDFORK_SON2_TIME )
|
||||
{
|
||||
const auto& gpo = db.get_global_properties();
|
||||
const asset_object& btc_asset = gpo.parameters.btc_asset()(db);
|
||||
if( btc_asset.is_transfer_restricted() ) {
|
||||
db.modify( btc_asset, []( asset_object& ao ) {
|
||||
ao.options.flags = asset_issuer_permission_flags::charge_market_fee |
|
||||
asset_issuer_permission_flags::override_authority;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props)
|
||||
{ try {
|
||||
const auto& gpo = get_global_properties();
|
||||
|
|
@ -1969,6 +1981,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
|
||||
rolling_period_start(*this);
|
||||
|
||||
update_son_asset(*this);
|
||||
|
||||
struct vote_tally_helper {
|
||||
database& d;
|
||||
const global_property_object& props;
|
||||
|
|
@ -1988,7 +2002,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
balance_type = vesting_balance_type::gpos;
|
||||
|
||||
const vesting_balance_index& vesting_index = d.get_index_type<vesting_balance_index>();
|
||||
#ifdef USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX
|
||||
|
||||
auto vesting_balances_begin =
|
||||
vesting_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(asset_id_type(), balance_type));
|
||||
auto vesting_balances_end =
|
||||
|
|
@ -2000,19 +2014,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
("owner", vesting_balance_obj.owner(d).name)
|
||||
("amount", vesting_balance_obj.balance.amount));
|
||||
}
|
||||
#else
|
||||
const auto& vesting_balances = vesting_index.indices().get<by_id>();
|
||||
for (const vesting_balance_object& vesting_balance_obj : vesting_balances)
|
||||
{
|
||||
if (vesting_balance_obj.balance.asset_id == asset_id_type() && vesting_balance_obj.balance.amount && vesting_balance_obj.balance_type == balance_type)
|
||||
{
|
||||
vesting_amounts[vesting_balance_obj.owner] += vesting_balance_obj.balance.amount;
|
||||
dlog("Vesting balance for account: ${owner}, amount: ${amount}",
|
||||
("owner", vesting_balance_obj.owner(d).name)
|
||||
("amount", vesting_balance_obj.balance.amount));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void operator()( const account_object& stake_account, const account_statistics_object& stats )
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <graphene/chain/witness_schedule_object.hpp>
|
||||
#include <graphene/chain/special_authority_object.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
#include <fc/io/fstream.hpp>
|
||||
|
|
@ -107,7 +108,6 @@ void database::reindex( fc::path data_dir )
|
|||
ilog( "reindexing blockchain" );
|
||||
auto start = fc::time_point::now();
|
||||
const auto last_block_num = last_block->block_num();
|
||||
uint32_t flush_point = last_block_num < 10000 ? 0 : last_block_num - 10000;
|
||||
uint32_t undo_point = last_block_num < 50 ? 0 : last_block_num - 50;
|
||||
|
||||
ilog( "Replaying blocks, starting at ${next}...", ("next",head_block_num() + 1) );
|
||||
|
|
@ -123,8 +123,7 @@ void database::reindex( fc::path data_dir )
|
|||
}
|
||||
for( uint32_t i = head_block_num() + 1; i <= last_block_num; ++i )
|
||||
{
|
||||
if( i % 10000 == 0 ) std::cerr << " " << double(i*100)/last_block_num << "% "<<i << " of " <<last_block_num<<" \n";
|
||||
if( i == flush_point )
|
||||
if( i % 10000 == 0 )
|
||||
{
|
||||
ilog( "Writing database to disk at block ${i}", ("i",i) );
|
||||
flush();
|
||||
|
|
@ -244,7 +243,7 @@ void database::close(bool rewind)
|
|||
{
|
||||
if (!_opened)
|
||||
return;
|
||||
|
||||
|
||||
// TODO: Save pending tx's on close()
|
||||
clear_pending();
|
||||
|
||||
|
|
@ -294,7 +293,7 @@ void database::force_slow_replays()
|
|||
void database::check_ending_lotteries()
|
||||
{
|
||||
try {
|
||||
const auto& lotteries_idx = get_index_type<asset_index>().indices().get<active_lotteries>();
|
||||
const auto& lotteries_idx = get_index_type<asset_index>().indices().get<active_lotteries>();
|
||||
for( auto checking_asset: lotteries_idx )
|
||||
{
|
||||
FC_ASSERT( checking_asset.is_lottery() );
|
||||
|
|
@ -306,6 +305,24 @@ void database::check_ending_lotteries()
|
|||
} catch( ... ) {}
|
||||
}
|
||||
|
||||
void database::check_ending_nft_lotteries()
|
||||
{
|
||||
try {
|
||||
const auto &nft_lotteries_idx = get_index_type<nft_metadata_index>().indices().get<active_nft_lotteries>();
|
||||
for (auto checking_token : nft_lotteries_idx)
|
||||
{
|
||||
FC_ASSERT(checking_token.is_lottery());
|
||||
const auto &lottery_options = checking_token.lottery_data->lottery_options;
|
||||
FC_ASSERT(lottery_options.is_active);
|
||||
// Check the current supply of lottery tokens
|
||||
auto current_supply = checking_token.get_token_current_supply(*this);
|
||||
if ((lottery_options.ending_on_soldout && (current_supply == checking_token.max_supply)) ||
|
||||
(lottery_options.end_date != time_point_sec() && (lottery_options.end_date <= head_block_time())))
|
||||
checking_token.end_lottery(*this);
|
||||
}
|
||||
} catch( ... ) {}
|
||||
}
|
||||
|
||||
void database::check_lottery_end_by_participants( asset_id_type asset_id )
|
||||
{
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <fc/container/flat.hpp>
|
||||
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/protocol/authority.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
|
|
@ -41,6 +42,10 @@
|
|||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/impacted.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/account_role_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
|
||||
|
||||
using namespace fc;
|
||||
|
|
@ -359,6 +364,13 @@ struct get_impacted_account_visitor
|
|||
void operator()( const account_role_delete_operation& op ){
|
||||
_impacted.insert( op.owner );
|
||||
}
|
||||
void operator()( const nft_lottery_token_purchase_operation& op ){
|
||||
_impacted.insert( op.buyer );
|
||||
}
|
||||
void operator()( const nft_lottery_reward_operation& op ) {
|
||||
_impacted.insert( op.winner );
|
||||
}
|
||||
void operator()( const nft_lottery_end_operation& op ) {}
|
||||
void operator()( const son_create_operation& op ) {
|
||||
_impacted.insert( op.owner_account );
|
||||
}
|
||||
|
|
@ -416,6 +428,9 @@ struct get_impacted_account_visitor
|
|||
void operator()( const sidechain_transaction_settle_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
}
|
||||
void operator()( const random_number_store_operation& op ) {
|
||||
_impacted.insert( op.account );
|
||||
}
|
||||
};
|
||||
|
||||
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result, bool ignore_custom_operation_required_auths ) {
|
||||
|
|
@ -528,6 +543,9 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
|
|||
} case sidechain_transaction_object_type:{
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( obj->id.space() == implementation_ids )
|
||||
|
|
@ -582,6 +600,10 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
|
|||
break;
|
||||
case impl_fba_accumulator_object_type:
|
||||
break;
|
||||
case impl_nft_lottery_balance_object_type:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )
|
||||
|
|
|
|||
|
|
@ -26,16 +26,18 @@
|
|||
#include <graphene/chain/db_with.hpp>
|
||||
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/betting_market_object.hpp>
|
||||
#include <graphene/chain/game_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/market_object.hpp>
|
||||
#include <graphene/chain/offer_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/son_proposal_object.hpp>
|
||||
#include <graphene/chain/tournament_object.hpp>
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/tournament_object.hpp>
|
||||
#include <graphene/chain/game_object.hpp>
|
||||
#include <graphene/chain/betting_market_object.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
|
|
@ -46,7 +48,6 @@ namespace graphene { namespace chain {
|
|||
void database::update_global_dynamic_data( const signed_block& b, const uint32_t missed_blocks )
|
||||
{
|
||||
const dynamic_global_property_object& _dgp = get_dynamic_global_properties();
|
||||
const global_property_object& gpo = get_global_properties();
|
||||
|
||||
// dynamic global properties updating
|
||||
modify( _dgp, [&b,this,missed_blocks]( dynamic_global_property_object& dgp ){
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#ifndef HARDFORK_1000_TIME
|
||||
#define HARDFORK_1000_TIME (fc::time_point_sec( 1550491200 ))
|
||||
#define HARDFORK_1000_TIME (fc::time_point_sec( 1540000000 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// added delete sport and delete event group operations
|
||||
#ifndef HARDFORK_1001_TIME
|
||||
#define HARDFORK_1001_TIME (fc::time_point_sec( 1550491200 ))
|
||||
#define HARDFORK_1001_TIME (fc::time_point_sec( 1540000000 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// 5050_1 HARDFORK Thursday, 22 April 2020 20:00:00 GMT
|
||||
// 5050_1 HARDFORK Wednesday, 15 April 2020 20:00:00 GMT
|
||||
#ifndef HARDFORK_5050_1_TIME
|
||||
#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1587585600 ))
|
||||
#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1586980800 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Placeholder HF for affiliate reward system
|
||||
#ifndef HARDFORK_999_TIME
|
||||
#define HARDFORK_999_TIME (fc::time_point_sec( 1550491200 ))
|
||||
#define HARDFORK_999_TIME (fc::time_point_sec( 1540000000 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// bitshares-core #429 rounding issue when creating assets
|
||||
#ifndef HARDFORK_CORE_429_TIME
|
||||
#define HARDFORK_CORE_429_TIME (fc::time_point_sec( 1568340000 ))
|
||||
#define HARDFORK_CORE_429_TIME (fc::time_point_sec( 1566784800 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// GPOS HARDFORK Monday, 17 February 2020 22:00:00 GMT
|
||||
// GPOS HARDFORK Monday, 6 January 2020 01:00:00 GMT
|
||||
#ifndef HARDFORK_GPOS_TIME
|
||||
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1581976800 ))
|
||||
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1578272400 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// GPOS HARDFORK 2020-12-21 00:00:00 GMT
|
||||
// NFT HARDFORK Sat, 15-Aug-20 00:00:00 UTC
|
||||
#ifndef HARDFORK_NFT_TIME
|
||||
#define HARDFORK_NFT_TIME (fc::time_point_sec( 1608508800 ))
|
||||
#define HARDFORK_NFT_TIME (fc::time_point_sec( 1597449600 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// GPOS HARDFORK 2020-12-21 00:00:00 GMT
|
||||
// SON HARDFORK Wednesday, October 28, 2020 0:00:00 GMT
|
||||
#ifndef HARDFORK_SON_TIME
|
||||
#define HARDFORK_SON_TIME (fc::time_point_sec( 1608508800 ))
|
||||
#define HARDFORK_SON_TIME (fc::time_point_sec( 1603843200 ))
|
||||
#endif
|
||||
|
|
|
|||
4
libraries/chain/hardfork.d/SON2.hf
Normal file
4
libraries/chain/hardfork.d/SON2.hf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// SON2 HARDFORK Friday, June 11, 2021 00:00:00 GMT
|
||||
#ifndef HARDFORK_SON2_TIME
|
||||
#define HARDFORK_SON2_TIME (fc::time_point_sec( 1623369600 ))
|
||||
#endif
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
#ifndef HARDFORK_SWEEPS_TIME
|
||||
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1568340000 ))
|
||||
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1566784800 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@ namespace graphene
|
|||
} // namespace graphene
|
||||
|
||||
FC_REFLECT_DERIVED(graphene::chain::account_role_object, (graphene::db::object),
|
||||
(owner)(name)(metadata)(allowed_operations)(whitelisted_accounts)(valid_to))
|
||||
(owner)(name)(metadata)(allowed_operations)(whitelisted_accounts)(valid_to))
|
||||
|
|
|
|||
|
|
@ -164,7 +164,12 @@ namespace graphene { namespace chain {
|
|||
|
||||
template<class DB>
|
||||
const asset_bitasset_data_object& bitasset_data(const DB& db)const
|
||||
{ assert(bitasset_data_id); return db.get(*bitasset_data_id); }
|
||||
{
|
||||
FC_ASSERT( bitasset_data_id.valid(),
|
||||
"Asset ${a} (${id}) is not a market issued asset.",
|
||||
("a",this->symbol)("id",this->id) );
|
||||
return db.get(*bitasset_data_id);
|
||||
}
|
||||
|
||||
template<class DB>
|
||||
const asset_dividend_data_object& dividend_data(const DB& db)const
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#define GRAPHENE_SYMBOL "PPY"
|
||||
#define GRAPHENE_ADDRESS_PREFIX "PPY"
|
||||
#define GRAPHENE_SYMBOL "TEST"
|
||||
#define GRAPHENE_ADDRESS_PREFIX "TEST"
|
||||
|
||||
#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH 1
|
||||
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH 63
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
void check_lottery_end_by_participants( asset_id_type asset_id );
|
||||
void check_ending_lotteries();
|
||||
void check_ending_nft_lotteries();
|
||||
|
||||
//////////////////// db_getter.cpp ////////////////////
|
||||
|
||||
|
|
@ -324,6 +325,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
uint32_t last_non_undoable_block_num() const;
|
||||
vector<authority> get_account_custom_authorities(account_id_type account, const operation& op)const;
|
||||
vector<uint64_t> get_random_numbers(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates);
|
||||
//////////////////// db_init.cpp ////////////////////
|
||||
|
||||
void initialize_evaluators();
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class global_betting_statistics_object : public graphene::db::abstract_object< g
|
|||
static const uint8_t space_id = implementation_ids;
|
||||
static const uint8_t type_id = impl_global_betting_statistics_object_type;
|
||||
|
||||
uint32_t number_of_active_events;
|
||||
uint32_t number_of_active_events = 0;
|
||||
map<asset_id_type, share_type> total_amount_staked;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,4 +38,4 @@ void transaction_get_impacted_accounts( const graphene::chain::transaction& tx,
|
|||
fc::flat_set<graphene::chain::account_id_type>& result,
|
||||
bool ignore_custom_operation_required_auths );
|
||||
|
||||
} } // graphene::app
|
||||
} } // graphene::app
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene
|
||||
{
|
||||
namespace chain
|
||||
{
|
||||
|
||||
class nft_lottery_token_purchase_evaluator : public evaluator<nft_lottery_token_purchase_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef nft_lottery_token_purchase_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const nft_lottery_token_purchase_operation &o);
|
||||
object_id_type do_apply(const nft_lottery_token_purchase_operation &o);
|
||||
};
|
||||
|
||||
class nft_lottery_reward_evaluator : public evaluator<nft_lottery_reward_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef nft_lottery_reward_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const nft_lottery_reward_operation &o);
|
||||
void_result do_apply(const nft_lottery_reward_operation &o);
|
||||
};
|
||||
|
||||
class nft_lottery_end_evaluator : public evaluator<nft_lottery_end_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef nft_lottery_end_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const nft_lottery_end_operation &o);
|
||||
void_result do_apply(const nft_lottery_end_operation &o);
|
||||
};
|
||||
|
||||
} // namespace chain
|
||||
} // namespace graphene
|
||||
|
|
@ -6,6 +6,29 @@
|
|||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
class nft_lottery_balance_object : public abstract_object<nft_lottery_balance_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = implementation_ids;
|
||||
static const uint8_t type_id = impl_nft_lottery_balance_object_type;
|
||||
|
||||
// Total Progressive jackpot carried over from previous lotteries
|
||||
asset total_progressive_jackpot;
|
||||
// Current total jackpot in this lottery inclusive of the progressive jackpot
|
||||
asset jackpot;
|
||||
// Total tickets sold
|
||||
share_type sweeps_tickets_sold;
|
||||
};
|
||||
|
||||
struct nft_lottery_data
|
||||
{
|
||||
nft_lottery_data() {}
|
||||
nft_lottery_data(const nft_lottery_options &options, nft_lottery_balance_id_type lottery_id)
|
||||
: lottery_options(options), lottery_balance_id(lottery_id) {}
|
||||
nft_lottery_options lottery_options;
|
||||
nft_lottery_balance_id_type lottery_balance_id;
|
||||
};
|
||||
|
||||
class nft_metadata_object : public abstract_object<nft_metadata_object>
|
||||
{
|
||||
public:
|
||||
|
|
@ -21,6 +44,21 @@ namespace graphene { namespace chain {
|
|||
bool is_transferable = false;
|
||||
bool is_sellable = true;
|
||||
optional<account_role_id_type> account_role;
|
||||
share_type max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
optional<nft_lottery_data> lottery_data;
|
||||
|
||||
nft_metadata_id_type get_id() const { return id; }
|
||||
bool is_lottery() const { return lottery_data.valid(); }
|
||||
uint32_t get_owner_num() const { return owner.instance.value; }
|
||||
time_point_sec get_lottery_expiration() const;
|
||||
asset get_lottery_jackpot(const database &db) const;
|
||||
share_type get_token_current_supply(const database &db) const;
|
||||
vector<account_id_type> get_holders(const database &db) const;
|
||||
vector<uint64_t> get_ticket_ids(const database &db) const;
|
||||
void distribute_benefactors_part(database &db);
|
||||
map<account_id_type, vector<uint16_t>> distribute_winners_part(database &db);
|
||||
void distribute_sweeps_holders_part(database &db);
|
||||
void end_lottery(database &db);
|
||||
};
|
||||
|
||||
class nft_object : public abstract_object<nft_object>
|
||||
|
|
@ -36,8 +74,23 @@ namespace graphene { namespace chain {
|
|||
std::string token_uri;
|
||||
};
|
||||
|
||||
struct nft_lottery_comparer
|
||||
{
|
||||
bool operator()(const nft_metadata_object& lhs, const nft_metadata_object& rhs) const
|
||||
{
|
||||
if ( !lhs.is_lottery() ) return false;
|
||||
if ( !lhs.lottery_data->lottery_options.is_active && !rhs.is_lottery()) return true; // not active lotteries first, just assets then
|
||||
if ( !lhs.lottery_data->lottery_options.is_active ) return false;
|
||||
if ( lhs.lottery_data->lottery_options.is_active && ( !rhs.is_lottery() || !rhs.lottery_data->lottery_options.is_active ) ) return true;
|
||||
return lhs.get_lottery_expiration() > rhs.get_lottery_expiration();
|
||||
}
|
||||
};
|
||||
|
||||
struct by_name;
|
||||
struct by_symbol;
|
||||
struct active_nft_lotteries;
|
||||
struct by_nft_lottery;
|
||||
struct by_nft_lottery_owner;
|
||||
using nft_metadata_multi_index_type = multi_index_container<
|
||||
nft_metadata_object,
|
||||
indexed_by<
|
||||
|
|
@ -49,6 +102,34 @@ namespace graphene { namespace chain {
|
|||
>,
|
||||
ordered_unique< tag<by_symbol>,
|
||||
member<nft_metadata_object, std::string, &nft_metadata_object::symbol>
|
||||
>,
|
||||
ordered_non_unique< tag<active_nft_lotteries>,
|
||||
identity< nft_metadata_object >,
|
||||
nft_lottery_comparer
|
||||
>,
|
||||
ordered_unique< tag<by_nft_lottery>,
|
||||
composite_key<
|
||||
nft_metadata_object,
|
||||
const_mem_fun<nft_metadata_object, bool, &nft_metadata_object::is_lottery>,
|
||||
member<object, object_id_type, &object::id>
|
||||
>,
|
||||
composite_key_compare<
|
||||
std::greater< bool >,
|
||||
std::greater< object_id_type >
|
||||
>
|
||||
>,
|
||||
ordered_unique< tag<by_nft_lottery_owner>,
|
||||
composite_key<
|
||||
nft_metadata_object,
|
||||
const_mem_fun<nft_metadata_object, bool, &nft_metadata_object::is_lottery>,
|
||||
const_mem_fun<nft_metadata_object, uint32_t, &nft_metadata_object::get_owner_num>,
|
||||
member<object, object_id_type, &object::id>
|
||||
>,
|
||||
composite_key_compare<
|
||||
std::greater< bool >,
|
||||
std::greater< uint32_t >,
|
||||
std::greater< object_id_type >
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
|
|
@ -86,8 +167,23 @@ namespace graphene { namespace chain {
|
|||
>;
|
||||
using nft_index = generic_index<nft_object, nft_multi_index_type>;
|
||||
|
||||
using nft_lottery_balance_index_type = multi_index_container<
|
||||
nft_lottery_balance_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >
|
||||
>
|
||||
>;
|
||||
using nft_lottery_balance_index = generic_index<nft_lottery_balance_object, nft_lottery_balance_index_type>;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::nft_lottery_balance_object, (graphene::db::object),
|
||||
(total_progressive_jackpot)
|
||||
(jackpot)
|
||||
(sweeps_tickets_sold) )
|
||||
|
||||
FC_REFLECT( graphene::chain::nft_lottery_data, (lottery_options)(lottery_balance_id) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::nft_metadata_object, (graphene::db::object),
|
||||
(owner)
|
||||
(name)
|
||||
|
|
@ -97,7 +193,9 @@ FC_REFLECT_DERIVED( graphene::chain::nft_metadata_object, (graphene::db::object)
|
|||
(revenue_split)
|
||||
(is_transferable)
|
||||
(is_sellable)
|
||||
(account_role) )
|
||||
(account_role)
|
||||
(max_supply)
|
||||
(lottery_data) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::nft_object, (graphene::db::object),
|
||||
(nft_metadata_id)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene
|
||||
{
|
||||
namespace chain
|
||||
{
|
||||
struct nft_lottery_token_purchase_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type
|
||||
{
|
||||
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
asset fee;
|
||||
// Lottery NFT Metadata
|
||||
nft_metadata_id_type lottery_id;
|
||||
// Buyer purchasing lottery tickets
|
||||
account_id_type buyer;
|
||||
// count of tickets to buy
|
||||
uint64_t tickets_to_buy;
|
||||
// amount that can spent
|
||||
asset amount;
|
||||
|
||||
extensions_type extensions;
|
||||
|
||||
account_id_type fee_payer() const { return buyer; }
|
||||
void validate() const;
|
||||
share_type calculate_fee(const fee_parameters_type &k) const;
|
||||
};
|
||||
|
||||
struct nft_lottery_reward_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type
|
||||
{
|
||||
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
// Lottery NFT Metadata
|
||||
nft_metadata_id_type lottery_id;
|
||||
// winner account
|
||||
account_id_type winner;
|
||||
// amount that won
|
||||
asset amount;
|
||||
// percentage of jackpot that user won
|
||||
uint16_t win_percentage;
|
||||
// true if recieved from benefators section of lottery; false otherwise
|
||||
bool is_benefactor_reward;
|
||||
|
||||
uint64_t winner_ticket_id;
|
||||
|
||||
extensions_type extensions;
|
||||
|
||||
account_id_type fee_payer() const { return account_id_type(); }
|
||||
void validate() const {};
|
||||
share_type calculate_fee(const fee_parameters_type &k) const { return k.fee; };
|
||||
};
|
||||
|
||||
struct nft_lottery_end_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type
|
||||
{
|
||||
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
// Lottery NFT Metadata
|
||||
nft_metadata_id_type lottery_id;
|
||||
|
||||
extensions_type extensions;
|
||||
|
||||
account_id_type fee_payer() const { return account_id_type(); }
|
||||
void validate() const {}
|
||||
share_type calculate_fee(const fee_parameters_type &k) const { return k.fee; }
|
||||
};
|
||||
|
||||
} // namespace chain
|
||||
} // namespace graphene
|
||||
|
||||
FC_REFLECT(graphene::chain::nft_lottery_token_purchase_operation::fee_parameters_type, (fee))
|
||||
FC_REFLECT(graphene::chain::nft_lottery_reward_operation::fee_parameters_type, (fee))
|
||||
FC_REFLECT(graphene::chain::nft_lottery_end_operation::fee_parameters_type, (fee))
|
||||
FC_REFLECT(graphene::chain::nft_lottery_token_purchase_operation, (fee)(lottery_id)(buyer)(tickets_to_buy)(amount)(extensions))
|
||||
FC_REFLECT(graphene::chain::nft_lottery_reward_operation, (fee)(lottery_id)(winner)(amount)(win_percentage)(is_benefactor_reward)(winner_ticket_id)(extensions))
|
||||
FC_REFLECT(graphene::chain::nft_lottery_end_operation, (fee)(lottery_id)(extensions))
|
||||
|
|
@ -4,6 +4,29 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct nft_lottery_benefactor {
|
||||
account_id_type id;
|
||||
uint16_t share; // percent * GRAPHENE_1_PERCENT
|
||||
nft_lottery_benefactor() = default;
|
||||
nft_lottery_benefactor( const nft_lottery_benefactor & ) = default;
|
||||
nft_lottery_benefactor( account_id_type _id, uint16_t _share ) : id( _id ), share( _share ) {}
|
||||
};
|
||||
|
||||
struct nft_lottery_options
|
||||
{
|
||||
std::vector<nft_lottery_benefactor> benefactors;
|
||||
// specifying winning tickets as shares that will be issued
|
||||
std::vector<uint16_t> winning_tickets;
|
||||
asset ticket_price;
|
||||
time_point_sec end_date;
|
||||
bool ending_on_soldout;
|
||||
bool is_active;
|
||||
bool delete_tickets_after_draw = false;
|
||||
std::vector<nft_metadata_id_type> progressive_jackpots;
|
||||
|
||||
void validate() const;
|
||||
};
|
||||
|
||||
struct nft_metadata_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type
|
||||
|
|
@ -23,6 +46,10 @@ namespace graphene { namespace chain {
|
|||
bool is_sellable = true;
|
||||
// Accounts Role
|
||||
optional<account_role_id_type> account_role;
|
||||
// Max number of NFTs that can be minted from the metadata
|
||||
optional<share_type> max_supply;
|
||||
// Lottery configuration
|
||||
optional<nft_lottery_options> lottery_options;
|
||||
extensions_type extensions;
|
||||
|
||||
account_id_type fee_payer()const { return owner; }
|
||||
|
|
@ -133,6 +160,9 @@ namespace graphene { namespace chain {
|
|||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::nft_lottery_benefactor, (id)(share) )
|
||||
FC_REFLECT( graphene::chain::nft_lottery_options, (benefactors)(winning_tickets)(ticket_price)(end_date)(ending_on_soldout)(is_active)(delete_tickets_after_draw)(progressive_jackpots) )
|
||||
|
||||
FC_REFLECT( graphene::chain::nft_metadata_create_operation::fee_parameters_type, (fee) (price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::nft_metadata_update_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::nft_mint_operation::fee_parameters_type, (fee) (price_per_kbyte) )
|
||||
|
|
@ -140,7 +170,7 @@ FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation::fee_parameters_ty
|
|||
FC_REFLECT( graphene::chain::nft_approve_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::nft_metadata_create_operation, (fee) (owner) (name) (symbol) (base_uri) (revenue_partner) (revenue_split) (is_transferable) (is_sellable) (account_role) (extensions) )
|
||||
FC_REFLECT( graphene::chain::nft_metadata_create_operation, (fee) (owner) (name) (symbol) (base_uri) (revenue_partner) (revenue_split) (is_transferable) (is_sellable) (account_role) (max_supply) (lottery_options) (extensions) )
|
||||
FC_REFLECT( graphene::chain::nft_metadata_update_operation, (fee) (owner) (nft_metadata_id) (name) (symbol) (base_uri) (revenue_partner) (revenue_split) (is_transferable) (is_sellable) (account_role) (extensions) )
|
||||
FC_REFLECT( graphene::chain::nft_mint_operation, (fee) (payer) (nft_metadata_id) (owner) (approved) (approved_operators) (token_uri) (extensions) )
|
||||
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation, (fee) (operator_) (from) (to) (token_id) (data) (extensions) )
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@
|
|||
#include <graphene/chain/protocol/offer.hpp>
|
||||
#include <graphene/chain/protocol/nft_ops.hpp>
|
||||
#include <graphene/chain/protocol/account_role.hpp>
|
||||
#include <graphene/chain/protocol/nft_lottery.hpp>
|
||||
#include <graphene/chain/protocol/son.hpp>
|
||||
#include <graphene/chain/protocol/sidechain_address.hpp>
|
||||
#include <graphene/chain/protocol/son_wallet.hpp>
|
||||
#include <graphene/chain/protocol/son_wallet_deposit.hpp>
|
||||
#include <graphene/chain/protocol/son_wallet_withdraw.hpp>
|
||||
#include <graphene/chain/protocol/sidechain_transaction.hpp>
|
||||
#include <graphene/chain/protocol/random_number.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -184,7 +186,11 @@ namespace graphene { namespace chain {
|
|||
sidechain_transaction_create_operation,
|
||||
sidechain_transaction_sign_operation,
|
||||
sidechain_transaction_send_operation,
|
||||
sidechain_transaction_settle_operation
|
||||
sidechain_transaction_settle_operation,
|
||||
nft_lottery_token_purchase_operation,
|
||||
nft_lottery_reward_operation,
|
||||
nft_lottery_end_operation,
|
||||
random_number_store_operation
|
||||
> operation;
|
||||
|
||||
/// @} // operations group
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct random_number_store_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
|
||||
account_id_type account;
|
||||
vector<uint64_t> random_number;
|
||||
std::string data;
|
||||
|
||||
account_id_type fee_payer()const { return account; }
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::random_number_store_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::random_number_store_operation, (fee)
|
||||
(account)
|
||||
(random_number)
|
||||
(data) )
|
||||
|
||||
|
|
@ -183,6 +183,7 @@ namespace graphene { namespace chain {
|
|||
son_wallet_withdraw_object_type,
|
||||
sidechain_address_object_type,
|
||||
sidechain_transaction_object_type,
|
||||
random_number_object_type,
|
||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
};
|
||||
|
||||
|
|
@ -214,7 +215,8 @@ namespace graphene { namespace chain {
|
|||
impl_sweeps_vesting_balance_object_type,
|
||||
impl_offer_history_object_type,
|
||||
impl_son_statistics_object_type,
|
||||
impl_son_schedule_object_type
|
||||
impl_son_schedule_object_type,
|
||||
impl_nft_lottery_balance_object_type
|
||||
};
|
||||
|
||||
//typedef fc::unsigned_int object_id_type;
|
||||
|
|
@ -258,6 +260,7 @@ namespace graphene { namespace chain {
|
|||
class son_wallet_withdraw_object;
|
||||
class sidechain_address_object;
|
||||
class sidechain_transaction_object;
|
||||
class random_number_object;
|
||||
|
||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||
|
|
@ -297,6 +300,7 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< protocol_ids, son_wallet_withdraw_object_type, son_wallet_withdraw_object> son_wallet_withdraw_id_type;
|
||||
typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type;
|
||||
typedef object_id< protocol_ids, sidechain_transaction_object_type,sidechain_transaction_object> sidechain_transaction_id_type;
|
||||
typedef object_id< protocol_ids, random_number_object_type, random_number_object> random_number_id_type;
|
||||
|
||||
// implementation types
|
||||
class global_property_object;
|
||||
|
|
@ -321,6 +325,7 @@ namespace graphene { namespace chain {
|
|||
class lottery_balance_object;
|
||||
class sweeps_vesting_balance_object;
|
||||
class offer_history_object;
|
||||
class nft_lottery_balance_object;
|
||||
class son_statistics_object;
|
||||
class son_schedule_object;
|
||||
|
||||
|
|
@ -352,6 +357,7 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< implementation_ids, impl_lottery_balance_object_type, lottery_balance_object > lottery_balance_id_type;
|
||||
typedef object_id< implementation_ids, impl_sweeps_vesting_balance_object_type, sweeps_vesting_balance_object> sweeps_vesting_balance_id_type;
|
||||
typedef object_id< implementation_ids, impl_offer_history_object_type, offer_history_object> offer_history_id_type;
|
||||
typedef object_id< implementation_ids, impl_nft_lottery_balance_object_type, nft_lottery_balance_object> nft_lottery_balance_id_type;
|
||||
typedef object_id< implementation_ids, impl_son_statistics_object_type, son_statistics_object > son_statistics_id_type;
|
||||
typedef object_id< implementation_ids, impl_son_schedule_object_type, son_schedule_object> son_schedule_id_type;
|
||||
|
||||
|
|
@ -496,6 +502,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
|||
(son_wallet_withdraw_object_type)
|
||||
(sidechain_address_object_type)
|
||||
(sidechain_transaction_object_type)
|
||||
(random_number_object_type)
|
||||
(OBJECT_TYPE_COUNT)
|
||||
)
|
||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||
|
|
@ -526,6 +533,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
|||
(impl_offer_history_object_type)
|
||||
(impl_son_statistics_object_type)
|
||||
(impl_son_schedule_object_type)
|
||||
(impl_nft_lottery_balance_object_type)
|
||||
)
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::share_type )
|
||||
|
|
@ -575,6 +583,7 @@ FC_REFLECT_TYPENAME( graphene::chain::offer_history_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::nft_metadata_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::nft_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::account_role_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::nft_lottery_balance_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_proposal_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_wallet_id_type )
|
||||
|
|
@ -582,7 +591,7 @@ FC_REFLECT_TYPENAME( graphene::chain::son_wallet_deposit_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::son_wallet_withdraw_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::sidechain_address_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::sidechain_transaction_id_type )
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::random_number_id_type )
|
||||
|
||||
FC_REFLECT( graphene::chain::void_t, )
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class random_number_store_evaluator : public evaluator<random_number_store_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef random_number_store_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const random_number_store_operation& o );
|
||||
object_id_type do_apply( const random_number_store_operation& o );
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
class random_number_object : public abstract_object<random_number_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = random_number_object_type;
|
||||
|
||||
account_id_type account; /* account who requested random number */
|
||||
time_point_sec timestamp; /* date and time when the number is read */
|
||||
vector<uint64_t> random_number; /* random number(s) */
|
||||
std::string data; /* custom data in json format */
|
||||
};
|
||||
|
||||
struct by_account;
|
||||
struct by_timestamp;
|
||||
using random_number_multi_index_type = multi_index_container<
|
||||
random_number_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>,
|
||||
member<object, object_id_type, &object::id>
|
||||
>,
|
||||
ordered_non_unique< tag<by_account>,
|
||||
member<random_number_object, account_id_type, &random_number_object::account>
|
||||
>,
|
||||
ordered_non_unique< tag<by_timestamp>,
|
||||
member<random_number_object, time_point_sec, &random_number_object::timestamp>
|
||||
>
|
||||
>
|
||||
>;
|
||||
using random_number_index = generic_index<random_number_object, random_number_multi_index_type>;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::random_number_object, (graphene::db::object),
|
||||
(account) (timestamp)
|
||||
(random_number) (data) )
|
||||
|
||||
|
|
@ -57,6 +57,9 @@ namespace graphene
|
|||
case operation::tag<account_role_create_operation>::value:
|
||||
case operation::tag<account_role_update_operation>::value:
|
||||
case operation::tag<account_role_delete_operation>::value:
|
||||
case operation::tag<nft_lottery_token_purchase_operation>::value:
|
||||
case operation::tag<nft_lottery_reward_operation>::value:
|
||||
case operation::tag<nft_lottery_end_operation>::value:
|
||||
FC_ASSERT(block_time >= HARDFORK_NFT_TIME, "Custom permissions and roles not allowed on this operation yet!");
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace graphene { namespace chain {
|
|||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = sidechain_transaction_object_type;
|
||||
|
||||
sidechain_type sidechain;
|
||||
sidechain_type sidechain = sidechain_type::unknown;
|
||||
object_id_type object_id;
|
||||
std::string transaction;
|
||||
std::vector<son_info> signers;
|
||||
|
|
@ -37,7 +37,7 @@ namespace graphene { namespace chain {
|
|||
uint32_t current_weight = 0;
|
||||
uint32_t threshold = 0;
|
||||
|
||||
sidechain_transaction_status status;
|
||||
sidechain_transaction_status status = sidechain_transaction_status::invalid;
|
||||
};
|
||||
|
||||
struct by_object_id;
|
||||
|
|
|
|||
|
|
@ -200,6 +200,20 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
struct by_account;
|
||||
struct by_asset_balance;
|
||||
|
||||
struct by_asset_balance_helper_asset_id {
|
||||
typedef asset_id_type result_type;
|
||||
result_type operator()(const vesting_balance_object& vbo) const {
|
||||
return vbo.balance.asset_id;
|
||||
}
|
||||
};
|
||||
struct by_asset_balance_helper_asset_amount {
|
||||
typedef share_type result_type;
|
||||
result_type operator()(const vesting_balance_object& vbo) const {
|
||||
return vbo.balance.amount;
|
||||
}
|
||||
};
|
||||
|
||||
typedef multi_index_container<
|
||||
vesting_balance_object,
|
||||
indexed_by<
|
||||
|
|
@ -210,11 +224,9 @@ namespace graphene { namespace chain {
|
|||
ordered_non_unique< tag<by_asset_balance>,
|
||||
composite_key<
|
||||
vesting_balance_object,
|
||||
member_offset<vesting_balance_object, asset_id_type, (size_t) (offsetof(vesting_balance_object,balance) + offsetof(asset,asset_id))>,
|
||||
by_asset_balance_helper_asset_id,
|
||||
member<vesting_balance_object, vesting_balance_type, &vesting_balance_object::balance_type>,
|
||||
member_offset<vesting_balance_object, share_type, (size_t) (offsetof(vesting_balance_object,balance) + offsetof(asset,amount))>
|
||||
//member<vesting_balance_object, account_id_type, &vesting_balance_object::owner>
|
||||
//member_offset<vesting_balance_object, account_id_type, (size_t) (offsetof(vesting_balance_object,owner))>
|
||||
by_asset_balance_helper_asset_amount
|
||||
>,
|
||||
composite_key_compare<
|
||||
std::less< asset_id_type >,
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <graphene/chain/index.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
void base_primary_index::save_undo( const object& obj )
|
||||
{ _db.save_undo( obj ); }
|
||||
|
||||
void base_primary_index::on_add( const object& obj )
|
||||
{
|
||||
_db.save_undo_add( obj );
|
||||
for( auto ob : _observers ) ob->on_add( obj );
|
||||
}
|
||||
|
||||
void base_primary_index::on_remove( const object& obj )
|
||||
{ _db.save_undo_remove( obj ); for( auto ob : _observers ) ob->on_remove( obj ); }
|
||||
|
||||
void base_primary_index::on_modify( const object& obj )
|
||||
{for( auto ob : _observers ) ob->on_modify( obj ); }
|
||||
} } // graphene::chain
|
||||
|
|
@ -24,6 +24,26 @@ void_result nft_metadata_create_evaluator::do_evaluate( const nft_metadata_creat
|
|||
const auto& ar_obj = (*op.account_role)(db());
|
||||
FC_ASSERT(ar_obj.owner == op.owner, "Only the Account Role created by the owner can be attached");
|
||||
}
|
||||
|
||||
// Lottery Related
|
||||
if (!op.lottery_options) {
|
||||
return void_result();
|
||||
}
|
||||
FC_ASSERT((*op.lottery_options).end_date > now || (*op.lottery_options).end_date == time_point_sec());
|
||||
if (op.max_supply) {
|
||||
FC_ASSERT(*op.max_supply >= 5);
|
||||
}
|
||||
|
||||
for(auto lottery_id: (*op.lottery_options).progressive_jackpots) {
|
||||
const auto& lottery_obj = lottery_id(db());
|
||||
FC_ASSERT(lottery_obj.owner == op.owner, "Only the Owner can attach progressive jackpots");
|
||||
FC_ASSERT(lottery_obj.is_lottery(), "Only lottery objects can be attached as progressive jackpots");
|
||||
FC_ASSERT(lottery_obj.lottery_data->lottery_options.is_active == false, "Lottery should not be active");
|
||||
FC_ASSERT(lottery_obj.lottery_data->lottery_options.ticket_price.asset_id == (*op.lottery_options).ticket_price.asset_id, "Lottery asset type should be same");
|
||||
const auto& lottery_balance_obj = lottery_obj.lottery_data->lottery_balance_id(db());
|
||||
FC_ASSERT(lottery_balance_obj.jackpot.amount > 0, "Non zero progressive jackpot not allowed");
|
||||
}
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
@ -39,6 +59,26 @@ object_id_type nft_metadata_create_evaluator::do_apply( const nft_metadata_creat
|
|||
obj.is_transferable = op.is_transferable;
|
||||
obj.is_sellable = op.is_sellable;
|
||||
obj.account_role = op.account_role;
|
||||
if (op.max_supply) {
|
||||
obj.max_supply = *op.max_supply;
|
||||
}
|
||||
if (op.lottery_options) {
|
||||
asset jackpot_sum(0,(*op.lottery_options).ticket_price.asset_id);
|
||||
for(auto lottery_id: (*op.lottery_options).progressive_jackpots) {
|
||||
const auto& lottery_obj = lottery_id(db());
|
||||
const auto& lottery_balance_obj = lottery_obj.lottery_data->lottery_balance_id(db());
|
||||
FC_ASSERT(lottery_balance_obj.jackpot.amount > 0, "Non zero progressive jackpot not allowed");
|
||||
db().modify(lottery_balance_obj, [&] ( nft_lottery_balance_object& nlbo ) {
|
||||
jackpot_sum += nlbo.jackpot;
|
||||
nlbo.jackpot -= nlbo.jackpot;
|
||||
});
|
||||
}
|
||||
const auto& new_lottery_balance_obj = db().create<nft_lottery_balance_object>([&](nft_lottery_balance_object& nlbo) {
|
||||
nlbo.total_progressive_jackpot = jackpot_sum;
|
||||
nlbo.jackpot = jackpot_sum;
|
||||
});
|
||||
obj.lottery_data = nft_lottery_data(*op.lottery_options, new_lottery_balance_obj.id);
|
||||
}
|
||||
});
|
||||
return new_nft_metadata_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
|
@ -110,6 +150,7 @@ void_result nft_mint_evaluator::do_evaluate( const nft_mint_operation& op )
|
|||
FC_ASSERT( itr_nft_md != idx_nft_md.end(), "NFT metadata not found" );
|
||||
FC_ASSERT( itr_nft_md->owner == op.payer, "Only metadata owner can mint NFT" );
|
||||
|
||||
FC_ASSERT(itr_nft_md->get_token_current_supply(db()) < itr_nft_md->max_supply, "NFTs can't be minted more than max_supply");
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
|
|||
145
libraries/chain/nft_lottery_evaluator.cpp
Normal file
145
libraries/chain/nft_lottery_evaluator.cpp
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#include <graphene/chain/nft_lottery_evaluator.hpp>
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/account_role_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
namespace graphene
|
||||
{
|
||||
namespace chain
|
||||
{
|
||||
void_result nft_lottery_token_purchase_evaluator::do_evaluate(const nft_lottery_token_purchase_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const database &d = db();
|
||||
auto now = d.head_block_time();
|
||||
FC_ASSERT(now >= HARDFORK_NFT_TIME, "Not allowed until NFT HF");
|
||||
op.buyer(d);
|
||||
const auto &lottery_md_obj = op.lottery_id(d);
|
||||
FC_ASSERT(lottery_md_obj.is_lottery(), "Not a lottery type");
|
||||
if (lottery_md_obj.account_role)
|
||||
{
|
||||
const auto &ar_idx = d.get_index_type<account_role_index>().indices().get<by_id>();
|
||||
auto ar_itr = ar_idx.find(*lottery_md_obj.account_role);
|
||||
if (ar_itr != ar_idx.end())
|
||||
{
|
||||
FC_ASSERT(d.account_role_valid(*ar_itr, op.buyer, get_type()), "Account role not valid");
|
||||
}
|
||||
}
|
||||
|
||||
auto lottery_options = lottery_md_obj.lottery_data->lottery_options;
|
||||
FC_ASSERT(lottery_options.ticket_price.asset_id == op.amount.asset_id);
|
||||
FC_ASSERT((double)op.amount.amount.value / lottery_options.ticket_price.amount.value == (double)op.tickets_to_buy);
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
object_id_type nft_lottery_token_purchase_evaluator::do_apply(const nft_lottery_token_purchase_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
transaction_evaluation_state nft_mint_context(&db());
|
||||
nft_mint_context.skip_fee_schedule_check = true;
|
||||
const auto &lottery_md_obj = op.lottery_id(db());
|
||||
nft_id_type nft_id;
|
||||
for (size_t i = 0; i < op.tickets_to_buy; i++)
|
||||
{
|
||||
nft_mint_operation mint_op;
|
||||
mint_op.payer = lottery_md_obj.owner;
|
||||
mint_op.nft_metadata_id = lottery_md_obj.id;
|
||||
mint_op.owner = op.buyer;
|
||||
nft_id = db().apply_operation(nft_mint_context, mint_op).get<object_id_type>();
|
||||
}
|
||||
db().adjust_balance(op.buyer, -op.amount);
|
||||
db().modify(lottery_md_obj.lottery_data->lottery_balance_id(db()), [&](nft_lottery_balance_object &obj) {
|
||||
obj.jackpot += op.amount;
|
||||
});
|
||||
return nft_id;
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
void_result nft_lottery_reward_evaluator::do_evaluate(const nft_lottery_reward_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const database &d = db();
|
||||
auto now = d.head_block_time();
|
||||
FC_ASSERT(now >= HARDFORK_NFT_TIME, "Not allowed until NFT HF");
|
||||
op.winner(d);
|
||||
|
||||
const auto &lottery_md_obj = op.lottery_id(d);
|
||||
FC_ASSERT(lottery_md_obj.is_lottery());
|
||||
|
||||
const auto &lottery_options = lottery_md_obj.lottery_data->lottery_options;
|
||||
FC_ASSERT(lottery_options.is_active);
|
||||
FC_ASSERT(lottery_md_obj.get_lottery_jackpot(d) >= op.amount);
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
void_result nft_lottery_reward_evaluator::do_apply(const nft_lottery_reward_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto &lottery_md_obj = op.lottery_id(db());
|
||||
db().adjust_balance(op.winner, op.amount);
|
||||
db().modify(lottery_md_obj.lottery_data->lottery_balance_id(db()), [&](nft_lottery_balance_object &obj) {
|
||||
obj.jackpot -= op.amount;
|
||||
});
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
void_result nft_lottery_end_evaluator::do_evaluate(const nft_lottery_end_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const database &d = db();
|
||||
auto now = d.head_block_time();
|
||||
FC_ASSERT(now >= HARDFORK_NFT_TIME, "Not allowed until NFT HF");
|
||||
const auto &lottery_md_obj = op.lottery_id(d);
|
||||
FC_ASSERT(lottery_md_obj.is_lottery());
|
||||
|
||||
const auto &lottery_options = lottery_md_obj.lottery_data->lottery_options;
|
||||
FC_ASSERT(lottery_options.is_active);
|
||||
FC_ASSERT(lottery_md_obj.get_lottery_jackpot(d).amount == 0);
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
|
||||
void_result nft_lottery_end_evaluator::do_apply(const nft_lottery_end_operation &op)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto &lottery_md_obj = op.lottery_id(db());
|
||||
db().modify(lottery_md_obj, [&](nft_metadata_object &obj) {
|
||||
obj.lottery_data->lottery_options.is_active = false;
|
||||
});
|
||||
db().modify(lottery_md_obj.lottery_data->lottery_balance_id(db()), [&](nft_lottery_balance_object &obj) {
|
||||
obj.sweeps_tickets_sold = lottery_md_obj.get_token_current_supply(db());
|
||||
});
|
||||
|
||||
if (lottery_md_obj.lottery_data->lottery_options.delete_tickets_after_draw)
|
||||
{
|
||||
const auto &nft_index_by_md = db().get_index_type<nft_index>().indices().get<by_metadata>();
|
||||
auto delete_nft_itr = nft_index_by_md.lower_bound(op.lottery_id);
|
||||
while (delete_nft_itr != nft_index_by_md.end() && delete_nft_itr->nft_metadata_id == op.lottery_id)
|
||||
{
|
||||
const nft_object &nft_obj = *delete_nft_itr;
|
||||
++delete_nft_itr;
|
||||
db().remove(nft_obj);
|
||||
}
|
||||
}
|
||||
|
||||
return void_result();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW((op))
|
||||
}
|
||||
} // namespace chain
|
||||
} // namespace graphene
|
||||
171
libraries/chain/nft_lottery_object.cpp
Normal file
171
libraries/chain/nft_lottery_object.cpp
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
|
||||
namespace graphene
|
||||
{
|
||||
namespace chain
|
||||
{
|
||||
time_point_sec nft_metadata_object::get_lottery_expiration() const
|
||||
{
|
||||
if (lottery_data)
|
||||
return lottery_data->lottery_options.end_date;
|
||||
return time_point_sec();
|
||||
}
|
||||
|
||||
asset nft_metadata_object::get_lottery_jackpot(const database &db) const
|
||||
{
|
||||
if (lottery_data)
|
||||
return lottery_data->lottery_balance_id(db).jackpot;
|
||||
return asset();
|
||||
}
|
||||
|
||||
share_type nft_metadata_object::get_token_current_supply(const database &db) const
|
||||
{
|
||||
share_type current_supply;
|
||||
const auto &idx_lottery_by_md = db.get_index_type<nft_index>().indices().get<by_metadata>();
|
||||
auto lottery_range = idx_lottery_by_md.equal_range(id);
|
||||
current_supply = std::distance(lottery_range.first, lottery_range.second);
|
||||
return current_supply;
|
||||
}
|
||||
|
||||
vector<account_id_type> nft_metadata_object::get_holders(const database &db) const
|
||||
{
|
||||
const auto &idx_lottery_by_md = db.get_index_type<nft_index>().indices().get<by_metadata>();
|
||||
auto lottery_range = idx_lottery_by_md.equal_range(id);
|
||||
vector<account_id_type> holders;
|
||||
holders.reserve(std::distance(lottery_range.first, lottery_range.second));
|
||||
std::for_each(lottery_range.first, lottery_range.second,
|
||||
[&](const nft_object &ticket) {
|
||||
holders.emplace_back(ticket.owner);
|
||||
});
|
||||
return holders;
|
||||
}
|
||||
|
||||
vector<uint64_t> nft_metadata_object::get_ticket_ids(const database &db) const
|
||||
{
|
||||
const auto &idx_lottery_by_md = db.get_index_type<nft_index>().indices().get<by_metadata>();
|
||||
auto lottery_range = idx_lottery_by_md.equal_range(id);
|
||||
vector<uint64_t> tickets;
|
||||
tickets.reserve(std::distance(lottery_range.first, lottery_range.second));
|
||||
std::for_each(lottery_range.first, lottery_range.second,
|
||||
[&](const nft_object &ticket) {
|
||||
tickets.emplace_back(ticket.id.instance());
|
||||
});
|
||||
return tickets;
|
||||
}
|
||||
|
||||
void nft_metadata_object::distribute_benefactors_part(database &db)
|
||||
{
|
||||
transaction_evaluation_state eval(&db);
|
||||
const auto &lottery_options = lottery_data->lottery_options;
|
||||
share_type jackpot = lottery_options.ticket_price.amount * get_token_current_supply(db) + lottery_data->lottery_balance_id(db).total_progressive_jackpot.amount;
|
||||
|
||||
for (auto benefactor : lottery_options.benefactors)
|
||||
{
|
||||
nft_lottery_reward_operation reward_op;
|
||||
reward_op.lottery_id = id;
|
||||
reward_op.winner = benefactor.id;
|
||||
reward_op.is_benefactor_reward = true;
|
||||
reward_op.win_percentage = benefactor.share;
|
||||
reward_op.amount = asset(jackpot.value * benefactor.share / GRAPHENE_100_PERCENT, lottery_options.ticket_price.asset_id);
|
||||
db.apply_operation(eval, reward_op);
|
||||
}
|
||||
}
|
||||
|
||||
map<account_id_type, vector<uint16_t>> nft_metadata_object::distribute_winners_part(database &db)
|
||||
{
|
||||
transaction_evaluation_state eval(&db);
|
||||
auto current_supply = get_token_current_supply(db);
|
||||
auto &lottery_options = lottery_data->lottery_options;
|
||||
|
||||
auto holders = get_holders(db);
|
||||
vector<uint64_t> ticket_ids = get_ticket_ids(db);
|
||||
FC_ASSERT(current_supply.value == (int64_t)holders.size());
|
||||
FC_ASSERT(get_lottery_jackpot(db).amount.value == current_supply.value * lottery_options.ticket_price.amount.value);
|
||||
map<account_id_type, vector<uint16_t>> structurized_participants;
|
||||
for (account_id_type holder : holders)
|
||||
{
|
||||
if (!structurized_participants.count(holder))
|
||||
structurized_participants.emplace(holder, vector<uint16_t>());
|
||||
}
|
||||
uint64_t jackpot = get_lottery_jackpot(db).amount.value;
|
||||
auto selections = lottery_options.winning_tickets.size() <= holders.size() ? lottery_options.winning_tickets.size() : holders.size();
|
||||
auto winner_numbers = db.get_random_numbers(0, holders.size(), selections, false);
|
||||
|
||||
auto &tickets(lottery_options.winning_tickets);
|
||||
|
||||
if (holders.size() < tickets.size())
|
||||
{
|
||||
uint16_t percents_to_distribute = 0;
|
||||
for (auto i = tickets.begin() + holders.size(); i != tickets.end();)
|
||||
{
|
||||
percents_to_distribute += *i;
|
||||
i = tickets.erase(i);
|
||||
}
|
||||
for (auto t = tickets.begin(); t != tickets.begin() + holders.size(); ++t)
|
||||
*t += percents_to_distribute / holders.size();
|
||||
}
|
||||
auto sweeps_distribution_percentage = db.get_global_properties().parameters.sweeps_distribution_percentage();
|
||||
for (size_t c = 0; c < winner_numbers.size(); ++c)
|
||||
{
|
||||
auto winner_num = winner_numbers[c];
|
||||
nft_lottery_reward_operation reward_op;
|
||||
reward_op.lottery_id = id;
|
||||
reward_op.is_benefactor_reward = false;
|
||||
reward_op.winner = holders[winner_num];
|
||||
if (ticket_ids.size() > winner_num)
|
||||
{
|
||||
reward_op.winner_ticket_id = ticket_ids[winner_num];
|
||||
}
|
||||
reward_op.win_percentage = tickets[c];
|
||||
reward_op.amount = asset(jackpot * tickets[c] * (1. - sweeps_distribution_percentage / (double)GRAPHENE_100_PERCENT) / GRAPHENE_100_PERCENT, lottery_options.ticket_price.asset_id);
|
||||
db.apply_operation(eval, reward_op);
|
||||
|
||||
structurized_participants[holders[winner_num]].push_back(tickets[c]);
|
||||
}
|
||||
return structurized_participants;
|
||||
}
|
||||
|
||||
void nft_metadata_object::distribute_sweeps_holders_part(database &db)
|
||||
{
|
||||
transaction_evaluation_state eval(&db);
|
||||
auto &asset_bal_idx = db.get_index_type<account_balance_index>().indices().get<by_asset_balance>();
|
||||
auto sweeps_params = db.get_global_properties().parameters;
|
||||
uint64_t distribution_asset_supply = sweeps_params.sweeps_distribution_asset()(db).dynamic_data(db).current_supply.value;
|
||||
const auto range = asset_bal_idx.equal_range(boost::make_tuple(sweeps_params.sweeps_distribution_asset()));
|
||||
asset remaining_jackpot = get_lottery_jackpot(db);
|
||||
uint64_t holders_sum = 0;
|
||||
for (const account_balance_object &holder_balance : boost::make_iterator_range(range.first, range.second))
|
||||
{
|
||||
int64_t holder_part = remaining_jackpot.amount.value / (double)distribution_asset_supply * holder_balance.balance.value * SWEEPS_VESTING_BALANCE_MULTIPLIER;
|
||||
db.adjust_sweeps_vesting_balance(holder_balance.owner, holder_part);
|
||||
holders_sum += holder_part;
|
||||
}
|
||||
uint64_t balance_rest = remaining_jackpot.amount.value * SWEEPS_VESTING_BALANCE_MULTIPLIER - holders_sum;
|
||||
db.adjust_sweeps_vesting_balance(sweeps_params.sweeps_vesting_accumulator_account(), balance_rest);
|
||||
db.modify(lottery_data->lottery_balance_id(db), [&](nft_lottery_balance_object &obj) {
|
||||
obj.jackpot -= remaining_jackpot;
|
||||
});
|
||||
}
|
||||
|
||||
void nft_metadata_object::end_lottery(database &db)
|
||||
{
|
||||
transaction_evaluation_state eval(&db);
|
||||
const auto &lottery_options = lottery_data->lottery_options;
|
||||
|
||||
FC_ASSERT(is_lottery());
|
||||
FC_ASSERT(lottery_options.is_active && (lottery_options.end_date <= db.head_block_time() || lottery_options.ending_on_soldout));
|
||||
|
||||
auto participants = distribute_winners_part(db);
|
||||
if (participants.size() > 0)
|
||||
{
|
||||
distribute_benefactors_part(db);
|
||||
distribute_sweeps_holders_part(db);
|
||||
}
|
||||
|
||||
nft_lottery_end_operation end_op;
|
||||
end_op.lottery_id = get_id();
|
||||
db.apply_operation(eval, end_op);
|
||||
}
|
||||
} // namespace chain
|
||||
} // namespace graphene
|
||||
|
|
@ -219,6 +219,18 @@ struct proposal_operation_hardfork_visitor
|
|||
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "account_role_delete_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const nft_lottery_token_purchase_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "nft_lottery_token_purchase_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const nft_lottery_reward_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "nft_lottery_reward_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const nft_lottery_end_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "nft_lottery_end_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const son_create_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_create_operation not allowed yet!" );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Peerplays Blockchain Standards Association, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <graphene/chain/protocol/competitor.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void competitor_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
|
|
@ -45,6 +45,10 @@ void nft_metadata_create_operation::validate() const
|
|||
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||
FC_ASSERT(is_valid_nft_token_name(name), "Invalid NFT name provided");
|
||||
FC_ASSERT(is_valid_nft_token_name(symbol), "Invalid NFT symbol provided");
|
||||
if (lottery_options)
|
||||
{
|
||||
(*lottery_options).validate();
|
||||
}
|
||||
}
|
||||
|
||||
void nft_metadata_update_operation::validate() const
|
||||
|
|
|
|||
38
libraries/chain/protocol/nft_lottery.cpp
Normal file
38
libraries/chain/protocol/nft_lottery.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#include <graphene/chain/protocol/nft_ops.hpp>
|
||||
#include <graphene/chain/protocol/nft_lottery.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
|
||||
namespace graphene
|
||||
{
|
||||
namespace chain
|
||||
{
|
||||
|
||||
void nft_lottery_options::validate() const
|
||||
{
|
||||
FC_ASSERT(winning_tickets.size() <= 64);
|
||||
FC_ASSERT(ticket_price.amount >= 1);
|
||||
uint16_t total = 0;
|
||||
for (auto benefactor : benefactors)
|
||||
{
|
||||
total += benefactor.share;
|
||||
}
|
||||
for (auto share : winning_tickets)
|
||||
{
|
||||
total += share;
|
||||
}
|
||||
FC_ASSERT(total == GRAPHENE_100_PERCENT, "distribution amount not equals GRAPHENE_100_PERCENT");
|
||||
FC_ASSERT(ending_on_soldout == true || end_date != time_point_sec(), "lottery may not end");
|
||||
}
|
||||
|
||||
share_type nft_lottery_token_purchase_operation::calculate_fee(const fee_parameters_type &k) const
|
||||
{
|
||||
return k.fee;
|
||||
}
|
||||
|
||||
void nft_lottery_token_purchase_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0, "Fee must not be negative");
|
||||
FC_ASSERT(tickets_to_buy > 0);
|
||||
}
|
||||
} // namespace chain
|
||||
} // namespace graphene
|
||||
24
libraries/chain/random_number_evaluator.cpp
Normal file
24
libraries/chain/random_number_evaluator.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <graphene/chain/random_number_evaluator.hpp>
|
||||
#include <graphene/chain/random_number_object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void_result random_number_store_evaluator::do_evaluate( const random_number_store_operation& op )
|
||||
{ try {
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type random_number_store_evaluator::do_apply( const random_number_store_operation& op )
|
||||
{ try {
|
||||
const auto& new_random_number_object = db().create<random_number_object>( [&]( random_number_object& obj ) {
|
||||
obj.account = op.account;
|
||||
obj.timestamp = db().head_block_time();
|
||||
obj.random_number = op.random_number;
|
||||
obj.data = op.data;
|
||||
});
|
||||
return new_random_number_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
|
|
@ -605,8 +605,9 @@ namespace graphene { namespace chain {
|
|||
return;
|
||||
|
||||
// We shouldn't be here if the final match is complete
|
||||
assert(last_complete_round != num_rounds - 1);
|
||||
if (last_complete_round == num_rounds - 1)
|
||||
uint32_t last_complete_round_uint32 = last_complete_round;
|
||||
assert(last_complete_round_uint32 != num_rounds - 1);
|
||||
if (last_complete_round_uint32 == num_rounds - 1)
|
||||
return;
|
||||
|
||||
if (first_incomplete_match_was_waiting)
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
const object* transaction_index::create(const std::function<void (object*)>& constructor, object_id_type)
|
||||
{
|
||||
transaction_object obj;
|
||||
|
||||
obj.id = get_next_available_id();
|
||||
constructor(&obj);
|
||||
|
||||
auto result = _index.insert(std::move(obj));
|
||||
FC_ASSERT(result.second, "Could not create transaction_object! Most likely a uniqueness constraint is violated.");
|
||||
return &*result.first;
|
||||
}
|
||||
|
||||
void transaction_index::modify(const object* obj,
|
||||
const std::function<void (object*)>& m)
|
||||
{
|
||||
assert(obj != nullptr);
|
||||
FC_ASSERT(obj->id < _index.size());
|
||||
|
||||
const transaction_object* t = dynamic_cast<const transaction_object*>(obj);
|
||||
assert(t != nullptr);
|
||||
|
||||
auto itr = _index.find(obj->id.instance());
|
||||
assert(itr != _index.end());
|
||||
_index.modify(itr, [&m](transaction_object& o) { m(&o); });
|
||||
}
|
||||
|
||||
void transaction_index::add(unique_ptr<object> o)
|
||||
{
|
||||
assert(o);
|
||||
object_id_type id = o->id;
|
||||
assert(id.space() == transaction_object::space_id);
|
||||
assert(id.type() == transaction_object::type_id);
|
||||
assert(id.instance() == size());
|
||||
|
||||
auto trx = dynamic_cast<transaction_object*>(o.get());
|
||||
assert(trx != nullptr);
|
||||
o.release();
|
||||
|
||||
auto result = _index.insert(std::move(*trx));
|
||||
FC_ASSERT(result.second, "Could not insert transaction_object! Most likely a uniqueness constraint is violated.");
|
||||
}
|
||||
|
||||
void transaction_index::remove(object_id_type id)
|
||||
{
|
||||
auto& index = _index.get<instance>();
|
||||
auto itr = index.find(id.instance());
|
||||
if( itr == index.end() )
|
||||
return;
|
||||
|
||||
assert(id.space() == transaction_object::space_id);
|
||||
assert(id.type() == transaction_object::type_id);
|
||||
|
||||
index.erase(itr);
|
||||
}
|
||||
|
||||
const object*transaction_index::get(object_id_type id) const
|
||||
{
|
||||
if( id.type() != transaction_object::type_id ||
|
||||
id.space() != transaction_object::space_id )
|
||||
return nullptr;
|
||||
|
||||
auto itr = _index.find(id.instance());
|
||||
if( itr == _index.end() )
|
||||
return nullptr;
|
||||
return &*itr;
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -59,17 +59,7 @@ namespace graphene { namespace db {
|
|||
{
|
||||
mv._apply_undo = false;
|
||||
}
|
||||
~session() {
|
||||
try {
|
||||
if( _apply_undo ) _db.undo();
|
||||
}
|
||||
catch ( const fc::exception& e )
|
||||
{
|
||||
elog( "${e}", ("e",e.to_detail_string() ) );
|
||||
throw; // maybe crash..
|
||||
}
|
||||
if( _disable_on_exit ) _db.disable();
|
||||
}
|
||||
~session();
|
||||
void commit() { _apply_undo = false; _db.commit(); }
|
||||
void undo() { if( _apply_undo ) _db.undo(); _apply_undo = false; }
|
||||
void merge() { if( _apply_undo ) _db.merge(); _apply_undo = false; }
|
||||
|
|
|
|||
|
|
@ -30,6 +30,18 @@ namespace graphene { namespace db {
|
|||
void undo_database::enable() { _disabled = false; }
|
||||
void undo_database::disable() { _disabled = true; }
|
||||
|
||||
undo_database::session::~session() {
|
||||
try {
|
||||
if( _apply_undo ) _db.undo();
|
||||
}
|
||||
catch ( const fc::exception& e )
|
||||
{
|
||||
elog( "${e}", ("e",e.to_detail_string() ) );
|
||||
std::terminate();
|
||||
}
|
||||
if( _disable_on_exit ) _db.disable();
|
||||
}
|
||||
|
||||
undo_database::session undo_database::start_undo_session( bool force_enable )
|
||||
{
|
||||
if( _disabled && !force_enable ) return session(*this);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_egenesis_none
|
|||
include/graphene/egenesis/egenesis.hpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_egenesis_none graphene_chain fc )
|
||||
target_link_libraries( graphene_egenesis_none graphene_chain )
|
||||
target_include_directories( graphene_egenesis_none
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ add_executable( embed_genesis
|
|||
embed_genesis.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( embed_genesis graphene_chain graphene_app graphene_egenesis_none fc )
|
||||
target_link_libraries( embed_genesis PRIVATE graphene_app graphene_egenesis_none )
|
||||
|
||||
set( embed_genesis_args
|
||||
-t "${CMAKE_CURRENT_SOURCE_DIR}/egenesis_brief.cpp.tmpl---${CMAKE_CURRENT_BINARY_DIR}/egenesis_brief.cpp"
|
||||
|
|
@ -42,8 +42,8 @@ add_custom_command(
|
|||
add_library( graphene_egenesis_brief "${CMAKE_CURRENT_BINARY_DIR}/egenesis_brief.cpp" include/graphene/egenesis/egenesis.hpp )
|
||||
add_library( graphene_egenesis_full "${CMAKE_CURRENT_BINARY_DIR}/egenesis_full.cpp" include/graphene/egenesis/egenesis.hpp )
|
||||
|
||||
target_link_libraries( graphene_egenesis_brief graphene_chain fc )
|
||||
target_link_libraries( graphene_egenesis_full graphene_chain fc )
|
||||
target_link_libraries( graphene_egenesis_brief graphene_chain )
|
||||
target_link_libraries( graphene_egenesis_full graphene_chain )
|
||||
|
||||
target_include_directories( graphene_egenesis_brief
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit fb27454cdf1626e5e108e42848bd1bcfe60c9540
|
||||
Subproject commit 488883921936139e8734b99822d3a589afe80da1
|
||||
|
|
@ -10,12 +10,8 @@ set(SOURCES node.cpp
|
|||
|
||||
add_library( graphene_net ${SOURCES} ${HEADERS} )
|
||||
|
||||
target_link_libraries( graphene_net
|
||||
PUBLIC fc graphene_db )
|
||||
target_include_directories( graphene_net
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../chain/include" "${CMAKE_CURRENT_BINARY_DIR}/../chain/include"
|
||||
)
|
||||
target_link_libraries( graphene_net graphene_chain )
|
||||
target_include_directories( graphene_net PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties( node.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
|
|
|
|||
|
|
@ -2375,6 +2375,7 @@ namespace graphene { namespace net { namespace detail {
|
|||
VERIFY_CORRECT_THREAD();
|
||||
item_hash_t reference_point = peer->last_block_delegate_has_seen;
|
||||
uint32_t reference_point_block_num = _delegate->get_block_number(peer->last_block_delegate_has_seen);
|
||||
(void)reference_point_block_num;
|
||||
|
||||
// when we call _delegate->get_blockchain_synopsis(), we may yield and there's a
|
||||
// chance this peer's state will change before we get control back. Save off
|
||||
|
|
@ -3414,6 +3415,7 @@ namespace graphene { namespace net { namespace detail {
|
|||
for (const item_hash_t& transaction_message_hash : contained_transaction_message_ids)
|
||||
{
|
||||
size_t items_erased = _items_to_fetch.get<item_id_index>().erase(item_id(trx_message_type, transaction_message_hash));
|
||||
(void)items_erased;
|
||||
// there are two ways we could behave here: we could either act as if we received
|
||||
// the transaction outside the block and offer it to our peers, or we could just
|
||||
// forget about it (we would still advertise this block to our peers so they should
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
add_subdirectory( witness )
|
||||
add_subdirectory( account_history )
|
||||
add_subdirectory( accounts_list )
|
||||
add_subdirectory( affiliate_stats )
|
||||
add_subdirectory( elasticsearch )
|
||||
add_subdirectory( market_history )
|
||||
add_subdirectory( delayed_node )
|
||||
add_subdirectory( bookie )
|
||||
add_subdirectory( debug_witness )
|
||||
add_subdirectory( delayed_node )
|
||||
add_subdirectory( elasticsearch )
|
||||
add_subdirectory( es_objects )
|
||||
add_subdirectory( generate_genesis )
|
||||
add_subdirectory( generate_uia_sharedrop_genesis )
|
||||
add_subdirectory( debug_witness )
|
||||
add_subdirectory( snapshot )
|
||||
add_subdirectory( market_history )
|
||||
add_subdirectory( peerplays_sidechain )
|
||||
add_subdirectory( es_objects )
|
||||
add_subdirectory( snapshot )
|
||||
add_subdirectory( witness )
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_account_history
|
|||
account_history_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_account_history graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_account_history PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_account_history
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_accounts_list
|
|||
accounts_list_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_accounts_list graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_accounts_list PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_accounts_list
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ add_library( graphene_affiliate_stats
|
|||
affiliate_stats_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_affiliate_stats graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_affiliate_stats PRIVATE graphene_plugin graphene_account_history )
|
||||
target_include_directories( graphene_affiliate_stats
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ add_library( graphene_bookie
|
|||
bookie_api.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_bookie graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_bookie PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_bookie
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ add_library( graphene_debug_witness
|
|||
debug_witness.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_debug_witness graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_debug_witness PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_debug_witness
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_delayed_node
|
|||
delayed_node_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_delayed_node graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_delayed_node PRIVATE graphene_plugin graphene_accounts_list graphene_affiliate_stats graphene_bookie graphene_debug_witness graphene_elasticsearch graphene_market_history )
|
||||
target_include_directories( graphene_delayed_node
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,21 @@ add_library( graphene_elasticsearch
|
|||
elasticsearch_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_elasticsearch graphene_chain graphene_app curl )
|
||||
target_include_directories( graphene_elasticsearch
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
find_curl()
|
||||
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
if(MSVC)
|
||||
set_source_files_properties(elasticsearch_plugin.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
endif(MSVC)
|
||||
if(CURL_STATICLIB)
|
||||
SET_TARGET_PROPERTIES(graphene_elasticsearch PROPERTIES
|
||||
COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
endif(CURL_STATICLIB)
|
||||
target_link_libraries( graphene_elasticsearch PRIVATE graphene_plugin ${CURL_LIBRARIES} )
|
||||
target_include_directories( graphene_elasticsearch
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
PUBLIC "${CURL_INCLUDE_DIR}" )
|
||||
|
||||
|
||||
install( TARGETS
|
||||
graphene_elasticsearch
|
||||
|
|
|
|||
|
|
@ -57,9 +57,9 @@ class elasticsearch_plugin_impl
|
|||
bool _elasticsearch_visitor = false;
|
||||
std::string _elasticsearch_basic_auth = "";
|
||||
std::string _elasticsearch_index_prefix = "peerplays-";
|
||||
bool _elasticsearch_operation_object = false;
|
||||
bool _elasticsearch_operation_object = true;
|
||||
uint32_t _elasticsearch_start_es_after_block = 0;
|
||||
bool _elasticsearch_operation_string = true;
|
||||
bool _elasticsearch_operation_string = false;
|
||||
mode _elasticsearch_mode = mode::only_save;
|
||||
CURL *curl; // curl handler
|
||||
vector <string> bulk_lines; // vector of op lines
|
||||
|
|
@ -75,20 +75,19 @@ class elasticsearch_plugin_impl
|
|||
std::string bulk_line;
|
||||
std::string index_name;
|
||||
bool is_sync = false;
|
||||
fc::time_point last_sync;
|
||||
private:
|
||||
bool add_elasticsearch( const account_id_type account_id, const optional<operation_history_object>& oho, const uint32_t block_number );
|
||||
const account_transaction_history_object& addNewEntry(const account_statistics_object& stats_obj,
|
||||
const account_id_type account_id,
|
||||
const account_id_type& account_id,
|
||||
const optional <operation_history_object>& oho);
|
||||
const account_statistics_object& getStatsObject(const account_id_type account_id);
|
||||
const account_statistics_object& getStatsObject(const account_id_type& account_id);
|
||||
void growStats(const account_statistics_object& stats_obj, const account_transaction_history_object& ath);
|
||||
void getOperationType(const optional <operation_history_object>& oho);
|
||||
void doOperationHistory(const optional <operation_history_object>& oho);
|
||||
void doBlock(const optional <operation_history_object>& oho, const signed_block& b);
|
||||
void doBlock(uint32_t trx_in_block, const signed_block& b);
|
||||
void doVisitor(const optional <operation_history_object>& oho);
|
||||
void checkState(const fc::time_point_sec& block_time);
|
||||
void cleanObjects(const account_transaction_history_object& ath, account_id_type account_id);
|
||||
void cleanObjects(const account_transaction_history_id_type& ath, const account_id_type& account_id);
|
||||
void createBulkLine(const account_transaction_history_object& ath);
|
||||
void prepareBulk(const account_transaction_history_id_type& ath_id);
|
||||
void populateESstruct();
|
||||
|
|
@ -148,7 +147,7 @@ bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b
|
|||
// populate what we can before impacted loop
|
||||
getOperationType(oho);
|
||||
doOperationHistory(oho);
|
||||
doBlock(oho, b);
|
||||
doBlock(oho->trx_in_block, b);
|
||||
if(_elasticsearch_visitor)
|
||||
doVisitor(oho);
|
||||
|
||||
|
|
@ -174,7 +173,11 @@ bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b
|
|||
for( auto& account_id : impacted )
|
||||
{
|
||||
if(!add_elasticsearch( account_id, oho, b.block_num() ))
|
||||
{
|
||||
elog( "Error adding data to Elastic Search: block num ${b}, account ${a}, data ${d}",
|
||||
("b",b.block_num()) ("a",account_id) ("d", oho) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// we send bulk at end of block when we are in sync for better real time client experience
|
||||
|
|
@ -185,23 +188,33 @@ bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b
|
|||
{
|
||||
prepare.clear();
|
||||
if(!graphene::utilities::SendBulk(es))
|
||||
{
|
||||
// Note: although called with `std::move()`, `es` is not updated in `SendBulk()`
|
||||
elog( "Error sending ${n} lines of bulk data to Elastic Search, the first lines are:",
|
||||
("n",es.bulk_lines.size()) );
|
||||
for( size_t i = 0; i < es.bulk_lines.size() && i < 10; ++i )
|
||||
{
|
||||
edump( (es.bulk_lines[i]) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
bulk_lines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if(bulk_lines.size() != limit_documents)
|
||||
bulk_lines.reserve(limit_documents);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void elasticsearch_plugin_impl::checkState(const fc::time_point_sec& block_time)
|
||||
{
|
||||
fc::time_point current_time(fc::time_point::now());
|
||||
if(((current_time - block_time) < fc::seconds(30)) || (current_time - last_sync > fc::seconds(60)))
|
||||
if((fc::time_point::now() - block_time) < fc::seconds(30))
|
||||
{
|
||||
limit_documents = _elasticsearch_bulk_sync;
|
||||
is_sync = true;
|
||||
last_sync = current_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -232,11 +245,11 @@ void elasticsearch_plugin_impl::doOperationHistory(const optional <operation_his
|
|||
os.op = fc::json::to_string(oho->op);
|
||||
}
|
||||
|
||||
void elasticsearch_plugin_impl::doBlock(const optional <operation_history_object>& oho, const signed_block& b)
|
||||
void elasticsearch_plugin_impl::doBlock(uint32_t trx_in_block, const signed_block& b)
|
||||
{
|
||||
std::string trx_id = "";
|
||||
if(oho->trx_in_block < b.transactions.size())
|
||||
trx_id = b.transactions[oho->trx_in_block].id().str();
|
||||
if(trx_in_block < b.transactions.size())
|
||||
trx_id = b.transactions[trx_in_block].id().str();
|
||||
bs.block_num = b.block_num();
|
||||
bs.block_time = b.timestamp;
|
||||
bs.trx_id = trx_id;
|
||||
|
|
@ -244,23 +257,41 @@ void elasticsearch_plugin_impl::doBlock(const optional <operation_history_object
|
|||
|
||||
void elasticsearch_plugin_impl::doVisitor(const optional <operation_history_object>& oho)
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
|
||||
operation_visitor o_v;
|
||||
oho->op.visit(o_v);
|
||||
|
||||
auto fee_asset = o_v.fee_asset(db);
|
||||
vs.fee_data.asset = o_v.fee_asset;
|
||||
vs.fee_data.asset_name = fee_asset.symbol;
|
||||
vs.fee_data.amount = o_v.fee_amount;
|
||||
vs.fee_data.amount_units = (o_v.fee_amount.value)/(double)asset::scaled_precision(fee_asset.precision).value;
|
||||
|
||||
auto transfer_asset = o_v.transfer_asset_id(db);
|
||||
vs.transfer_data.asset = o_v.transfer_asset_id;
|
||||
vs.transfer_data.asset_name = transfer_asset.symbol;
|
||||
vs.transfer_data.amount = o_v.transfer_amount;
|
||||
vs.transfer_data.amount_units = (o_v.transfer_amount.value)/(double)asset::scaled_precision(transfer_asset.precision).value;
|
||||
vs.transfer_data.from = o_v.transfer_from;
|
||||
vs.transfer_data.to = o_v.transfer_to;
|
||||
|
||||
auto fill_pays_asset = o_v.fill_pays_asset_id(db);
|
||||
auto fill_receives_asset = o_v.fill_receives_asset_id(db);
|
||||
vs.fill_data.order_id = o_v.fill_order_id;
|
||||
vs.fill_data.account_id = o_v.fill_account_id;
|
||||
vs.fill_data.pays_asset_id = o_v.fill_pays_asset_id;
|
||||
vs.fill_data.pays_asset_name = fill_pays_asset.symbol;
|
||||
vs.fill_data.pays_amount = o_v.fill_pays_amount;
|
||||
vs.fill_data.pays_amount_units = (o_v.fill_pays_amount.value)/(double)asset::scaled_precision(fill_pays_asset.precision).value;
|
||||
vs.fill_data.receives_asset_id = o_v.fill_receives_asset_id;
|
||||
vs.fill_data.receives_asset_name = fill_receives_asset.symbol;
|
||||
vs.fill_data.receives_amount = o_v.fill_receives_amount;
|
||||
vs.fill_data.receives_amount_units = (o_v.fill_receives_amount.value)/(double)asset::scaled_precision(fill_receives_asset.precision).value;
|
||||
|
||||
auto fill_price = (o_v.fill_receives_amount.value/(double)asset::scaled_precision(fill_receives_asset.precision).value) /
|
||||
(o_v.fill_pays_amount.value/(double)asset::scaled_precision(fill_pays_asset.precision).value);
|
||||
vs.fill_data.fill_price_units = fill_price;
|
||||
//vs.fill_data.fill_price = o_v.fill_fill_price;
|
||||
//vs.fill_data.is_maker = o_v.fill_is_maker;
|
||||
}
|
||||
|
|
@ -276,13 +307,22 @@ bool elasticsearch_plugin_impl::add_elasticsearch( const account_id_type account
|
|||
createBulkLine(ath);
|
||||
prepareBulk(ath.id);
|
||||
}
|
||||
cleanObjects(ath, account_id);
|
||||
cleanObjects(ath.id, account_id);
|
||||
|
||||
if (curl && bulk_lines.size() >= limit_documents) { // we are in bulk time, ready to add data to elasticsearech
|
||||
prepare.clear();
|
||||
populateESstruct();
|
||||
if(!graphene::utilities::SendBulk(es))
|
||||
{
|
||||
// Note: although called with `std::move()`, `es` is not updated in `SendBulk()`
|
||||
elog( "Error sending ${n} lines of bulk data to Elastic Search, the first lines are:",
|
||||
("n",es.bulk_lines.size()) );
|
||||
for( size_t i = 0; i < es.bulk_lines.size() && i < 10; ++i )
|
||||
{
|
||||
edump( (es.bulk_lines[i]) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
bulk_lines.clear();
|
||||
}
|
||||
|
|
@ -290,15 +330,16 @@ bool elasticsearch_plugin_impl::add_elasticsearch( const account_id_type account
|
|||
return true;
|
||||
}
|
||||
|
||||
const account_statistics_object& elasticsearch_plugin_impl::getStatsObject(const account_id_type account_id)
|
||||
const account_statistics_object& elasticsearch_plugin_impl::getStatsObject(const account_id_type& account_id)
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
const auto &acct = db.get<account_object>(account_id);
|
||||
return acct.statistics(db);
|
||||
const auto &stats_obj = db.get_account_stats_by_owner(account_id);
|
||||
|
||||
return stats_obj;
|
||||
}
|
||||
|
||||
const account_transaction_history_object& elasticsearch_plugin_impl::addNewEntry(const account_statistics_object& stats_obj,
|
||||
const account_id_type account_id,
|
||||
const account_id_type& account_id,
|
||||
const optional <operation_history_object>& oho)
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
|
|
@ -340,19 +381,21 @@ void elasticsearch_plugin_impl::prepareBulk(const account_transaction_history_id
|
|||
fc::mutable_variant_object bulk_header;
|
||||
bulk_header["_index"] = index_name;
|
||||
bulk_header["_type"] = "data";
|
||||
bulk_header["_id"] = fc::to_string(ath_id.space_id) + "." + fc::to_string(ath_id.type_id) + "." + ath_id.instance;
|
||||
prepare = graphene::utilities::createBulk(bulk_header, bulk_line);
|
||||
bulk_lines.insert(bulk_lines.end(), prepare.begin(), prepare.end());
|
||||
bulk_header["_id"] = fc::to_string(ath_id.space_id) + "." + fc::to_string(ath_id.type_id) + "."
|
||||
+ fc::to_string(ath_id.instance.value);
|
||||
prepare = graphene::utilities::createBulk(bulk_header, std::move(bulk_line));
|
||||
std::move(prepare.begin(), prepare.end(), std::back_inserter(bulk_lines));
|
||||
prepare.clear();
|
||||
}
|
||||
|
||||
void elasticsearch_plugin_impl::cleanObjects(const account_transaction_history_object& ath, account_id_type account_id)
|
||||
void elasticsearch_plugin_impl::cleanObjects(const account_transaction_history_id_type& ath_id, const account_id_type& account_id)
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
// remove everything except current object from ath
|
||||
const auto &his_idx = db.get_index_type<account_transaction_history_index>();
|
||||
const auto &by_seq_idx = his_idx.indices().get<by_seq>();
|
||||
auto itr = by_seq_idx.lower_bound(boost::make_tuple(account_id, 0));
|
||||
if (itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath.id) {
|
||||
if (itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath_id) {
|
||||
// if found, remove the entry
|
||||
const auto remove_op_id = itr->operation_id;
|
||||
const auto itr_remove = itr;
|
||||
|
|
@ -377,9 +420,12 @@ void elasticsearch_plugin_impl::cleanObjects(const account_transaction_history_o
|
|||
void elasticsearch_plugin_impl::populateESstruct()
|
||||
{
|
||||
es.curl = curl;
|
||||
es.bulk_lines = bulk_lines;
|
||||
es.bulk_lines = std::move(bulk_lines);
|
||||
es.elasticsearch_url = _elasticsearch_node_url;
|
||||
es.auth = _elasticsearch_basic_auth;
|
||||
es.index_prefix = _elasticsearch_index_prefix;
|
||||
es.endpoint = "";
|
||||
es.query = "";
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
|
@ -421,11 +467,11 @@ void elasticsearch_plugin::plugin_set_program_options(
|
|||
("elasticsearch-index-prefix", boost::program_options::value<std::string>(),
|
||||
"Add a prefix to the index(peerplays-)")
|
||||
("elasticsearch-operation-object", boost::program_options::value<bool>(),
|
||||
"Save operation as object(false)")
|
||||
"Save operation as object(true)")
|
||||
("elasticsearch-start-es-after-block", boost::program_options::value<uint32_t>(),
|
||||
"Start doing ES job after block(0)")
|
||||
("elasticsearch-operation-string", boost::program_options::value<bool>(),
|
||||
"Save operation as string. Needed to serve history api calls(true)")
|
||||
"Save operation as string. Needed to serve history api calls(false)")
|
||||
("elasticsearch-mode", boost::program_options::value<uint16_t>(),
|
||||
"Mode of operation: only_save(0), only_query(1), all(2) - Default: 0")
|
||||
;
|
||||
|
|
@ -467,18 +513,18 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia
|
|||
if (options.count("elasticsearch-mode")) {
|
||||
const auto option_number = options["elasticsearch-mode"].as<uint16_t>();
|
||||
if(option_number > mode::all)
|
||||
FC_THROW_EXCEPTION(fc::exception, "Elasticsearch mode not valid");
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Elasticsearch mode not valid");
|
||||
my->_elasticsearch_mode = static_cast<mode>(options["elasticsearch-mode"].as<uint16_t>());
|
||||
}
|
||||
|
||||
if(my->_elasticsearch_mode != mode::only_query) {
|
||||
if (my->_elasticsearch_mode == mode::all && !my->_elasticsearch_operation_string)
|
||||
FC_THROW_EXCEPTION(fc::exception,
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception,
|
||||
"If elasticsearch-mode is set to all then elasticsearch-operation-string need to be true");
|
||||
|
||||
database().applied_block.connect([this](const signed_block &b) {
|
||||
if (!my->update_account_histories(b))
|
||||
FC_THROW_EXCEPTION(fc::exception,
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception,
|
||||
"Error populating ES database, we are going to keep trying.");
|
||||
});
|
||||
}
|
||||
|
|
@ -563,13 +609,12 @@ vector<operation_history_object> elasticsearch_plugin::get_account_history(
|
|||
const auto response = graphene::utilities::simpleQuery(es);
|
||||
variant variant_response = fc::json::from_string(response);
|
||||
|
||||
const auto hits = variant_response["hits"]["total"]["value"];
|
||||
const auto hits = variant_response["hits"]["total"];
|
||||
uint32_t size;
|
||||
if( hits.is_object() ) // ES-7 ?
|
||||
size = static_cast<uint32_t>(hits["value"].as_uint64());
|
||||
else // probably ES-6
|
||||
size = static_cast<uint32_t>(hits.as_uint64());
|
||||
|
||||
size = std::min( size, limit );
|
||||
|
||||
for(unsigned i=0; i<size; i++)
|
||||
|
|
|
|||
|
|
@ -152,12 +152,16 @@ struct block_struct {
|
|||
|
||||
struct fee_struct {
|
||||
asset_id_type asset;
|
||||
std::string asset_name;
|
||||
share_type amount;
|
||||
double amount_units;
|
||||
};
|
||||
|
||||
struct transfer_struct {
|
||||
asset_id_type asset;
|
||||
std::string asset_name;
|
||||
share_type amount;
|
||||
double amount_units;
|
||||
account_id_type from;
|
||||
account_id_type to;
|
||||
};
|
||||
|
|
@ -166,10 +170,15 @@ struct fill_struct {
|
|||
object_id_type order_id;
|
||||
account_id_type account_id;
|
||||
asset_id_type pays_asset_id;
|
||||
std::string pays_asset_name;
|
||||
share_type pays_amount;
|
||||
double pays_amount_units;
|
||||
asset_id_type receives_asset_id;
|
||||
std::string receives_asset_name;
|
||||
share_type receives_amount;
|
||||
double receives_amount_units;
|
||||
double fill_price;
|
||||
double fill_price_units;
|
||||
bool is_maker;
|
||||
};
|
||||
|
||||
|
|
@ -258,6 +267,23 @@ struct adaptor_struct {
|
|||
{
|
||||
o["initializer"] = fc::json::to_string(o["initializer"]);
|
||||
}
|
||||
if (o.find("policy") != o.end())
|
||||
{
|
||||
o["policy"] = fc::json::to_string(o["policy"]);
|
||||
}
|
||||
if (o.find("predicates") != o.end())
|
||||
{
|
||||
o["predicates"] = fc::json::to_string(o["predicates"]);
|
||||
}
|
||||
if (o.find("active_special_authority") != o.end())
|
||||
{
|
||||
o["active_special_authority"] = fc::json::to_string(o["active_special_authority"]);
|
||||
}
|
||||
if (o.find("owner_special_authority") != o.end())
|
||||
{
|
||||
o["owner_special_authority"] = fc::json::to_string(o["owner_special_authority"]);
|
||||
}
|
||||
|
||||
|
||||
variant v;
|
||||
fc::to_variant(o, v, FC_PACK_MAX_DEPTH);
|
||||
|
|
@ -277,13 +303,16 @@ struct adaptor_struct {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
} } //graphene::elasticsearch
|
||||
|
||||
FC_REFLECT_ENUM( graphene::elasticsearch::mode, (only_save)(only_query)(all) )
|
||||
FC_REFLECT( graphene::elasticsearch::operation_history_struct, (trx_in_block)(op_in_trx)(operation_result)(virtual_op)(op)(op_object) )
|
||||
FC_REFLECT( graphene::elasticsearch::block_struct, (block_num)(block_time)(trx_id) )
|
||||
FC_REFLECT( graphene::elasticsearch::fee_struct, (asset)(amount) )
|
||||
FC_REFLECT( graphene::elasticsearch::transfer_struct, (asset)(amount)(from)(to) )
|
||||
FC_REFLECT( graphene::elasticsearch::fill_struct, (order_id)(account_id)(pays_asset_id)(pays_amount)(receives_asset_id)(receives_amount)(fill_price)(is_maker))
|
||||
FC_REFLECT( graphene::elasticsearch::fee_struct, (asset)(asset_name)(amount)(amount_units) )
|
||||
FC_REFLECT( graphene::elasticsearch::transfer_struct, (asset)(asset_name)(amount)(amount_units)(from)(to) )
|
||||
FC_REFLECT( graphene::elasticsearch::fill_struct, (order_id)(account_id)(pays_asset_id)(pays_asset_name)(pays_amount)(pays_amount_units)
|
||||
(receives_asset_id)(receives_asset_name)(receives_amount)(receives_amount_units)(fill_price)
|
||||
(fill_price_units)(is_maker))
|
||||
FC_REFLECT( graphene::elasticsearch::visitor_struct, (fee_data)(transfer_data)(fill_data) )
|
||||
FC_REFLECT( graphene::elasticsearch::bulk_struct, (account_history)(operation_history)(operation_type)(operation_id_num)(block_data)(additional_data) )
|
||||
|
|
|
|||
|
|
@ -4,14 +4,22 @@ add_library( graphene_es_objects
|
|||
es_objects.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_es_objects graphene_chain graphene_app curl )
|
||||
target_include_directories( graphene_es_objects
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
find_curl()
|
||||
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
if(CURL_STATICLIB)
|
||||
SET_TARGET_PROPERTIES(graphene_es_objects PROPERTIES
|
||||
COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
endif(CURL_STATICLIB)
|
||||
if(MSVC)
|
||||
set_source_files_properties(es_objects.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
endif(MSVC)
|
||||
|
||||
target_link_libraries( graphene_es_objects PRIVATE graphene_plugin ${CURL_LIBRARIES} )
|
||||
target_include_directories( graphene_es_objects
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
||||
install( TARGETS
|
||||
graphene_es_objects
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,22 @@
|
|||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
|
||||
#include <graphene/chain/account_role_object.hpp>
|
||||
#include <graphene/chain/committee_member_object.hpp>
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
#include <graphene/chain/offer_object.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/chain/sidechain_transaction_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/son_proposal_object.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/chain/son_wallet_deposit_object.hpp>
|
||||
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
|
||||
#include <graphene/utilities/elasticsearch.hpp>
|
||||
|
||||
namespace graphene { namespace es_objects {
|
||||
|
|
@ -61,6 +77,16 @@ class es_objects_plugin_impl
|
|||
bool _es_objects_balances = true;
|
||||
bool _es_objects_limit_orders = true;
|
||||
bool _es_objects_asset_bitasset = true;
|
||||
|
||||
bool _es_objects_account_role = true;
|
||||
bool _es_objects_committee_member = true;
|
||||
bool _es_objects_nft = true;
|
||||
bool _es_objects_son = true;
|
||||
bool _es_objects_transaction = true;
|
||||
bool _es_objects_vesting_balance = true;
|
||||
bool _es_objects_witness = true;
|
||||
bool _es_objects_worker = true;
|
||||
|
||||
std::string _es_objects_index_prefix = "ppobjects-";
|
||||
uint32_t _es_objects_start_es_after_block = 0;
|
||||
CURL *curl; // curl handler
|
||||
|
|
@ -79,7 +105,6 @@ class es_objects_plugin_impl
|
|||
|
||||
bool es_objects_plugin_impl::genesis()
|
||||
{
|
||||
|
||||
ilog("elasticsearch OBJECTS: inserting data from genesis");
|
||||
|
||||
graphene::chain::database &db = _self.database();
|
||||
|
|
@ -112,13 +137,142 @@ bool es_objects_plugin_impl::genesis()
|
|||
});
|
||||
}
|
||||
|
||||
if (_es_objects_account_role) {
|
||||
auto &idx = db.get_index_type<graphene::chain::account_role_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const account_role_object *>(obj);
|
||||
prepareTemplate<account_role_object>(*b, "account_role");
|
||||
});
|
||||
}
|
||||
if (_es_objects_committee_member) {
|
||||
auto &idx = db.get_index_type<graphene::chain::committee_member_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const committee_member_object *>(obj);
|
||||
prepareTemplate<committee_member_object>(*b, "committee_member");
|
||||
});
|
||||
}
|
||||
if (_es_objects_nft) {
|
||||
auto &idx = db.get_index_type<graphene::chain::nft_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const nft_object *>(obj);
|
||||
prepareTemplate<nft_object>(*b, "nft");
|
||||
});
|
||||
}
|
||||
if (_es_objects_nft) {
|
||||
auto &idx = db.get_index_type<graphene::chain::nft_metadata_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const nft_metadata_object *>(obj);
|
||||
prepareTemplate<nft_metadata_object>(*b, "nft_metadata");
|
||||
});
|
||||
}
|
||||
if (_es_objects_nft) {
|
||||
auto &idx = db.get_index_type<graphene::chain::offer_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const offer_object *>(obj);
|
||||
prepareTemplate<offer_object>(*b, "offer");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::sidechain_address_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const sidechain_address_object *>(obj);
|
||||
prepareTemplate<sidechain_address_object>(*b, "sidechain_address");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::sidechain_transaction_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const sidechain_transaction_object *>(obj);
|
||||
prepareTemplate<sidechain_transaction_object>(*b, "sidechain_transaction");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::son_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const son_object *>(obj);
|
||||
prepareTemplate<son_object>(*b, "son");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::son_proposal_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const son_proposal_object *>(obj);
|
||||
prepareTemplate<son_proposal_object>(*b, "son_proposal");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::son_wallet_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const son_wallet_object *>(obj);
|
||||
prepareTemplate<son_wallet_object>(*b, "son_wallet");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::son_wallet_deposit_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const son_wallet_deposit_object *>(obj);
|
||||
prepareTemplate<son_wallet_deposit_object>(*b, "son_wallet_deposit");
|
||||
});
|
||||
}
|
||||
if (_es_objects_son) {
|
||||
auto &idx = db.get_index_type<graphene::chain::son_wallet_withdraw_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const son_wallet_withdraw_object *>(obj);
|
||||
prepareTemplate<son_wallet_withdraw_object>(*b, "son_wallet_withdraw");
|
||||
});
|
||||
}
|
||||
if (_es_objects_transaction) {
|
||||
auto &idx = db.get_index_type<graphene::chain::transaction_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const transaction_object *>(obj);
|
||||
prepareTemplate<transaction_object>(*b, "transaction");
|
||||
});
|
||||
}
|
||||
if (_es_objects_vesting_balance) {
|
||||
auto &idx = db.get_index_type<graphene::chain::vesting_balance_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const vesting_balance_object *>(obj);
|
||||
prepareTemplate<vesting_balance_object>(*b, "vesting_balance");
|
||||
});
|
||||
}
|
||||
if (_es_objects_witness) {
|
||||
auto &idx = db.get_index_type<graphene::chain::witness_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const witness_object *>(obj);
|
||||
prepareTemplate<witness_object>(*b, "witness");
|
||||
});
|
||||
}
|
||||
if (_es_objects_worker) {
|
||||
auto &idx = db.get_index_type<graphene::chain::worker_index>();
|
||||
idx.inspect_all_objects([this, &db](const graphene::db::object &o) {
|
||||
auto obj = db.find_object(o.id);
|
||||
auto b = static_cast<const worker_object *>(obj);
|
||||
prepareTemplate<worker_object>(*b, "worker");
|
||||
});
|
||||
}
|
||||
|
||||
graphene::utilities::ES es;
|
||||
es.curl = curl;
|
||||
es.bulk_lines = bulk;
|
||||
es.elasticsearch_url = _es_objects_elasticsearch_url;
|
||||
es.auth = _es_objects_auth;
|
||||
if (!graphene::utilities::SendBulk(es))
|
||||
FC_THROW_EXCEPTION(fc::exception, "Error inserting genesis data.");
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Error inserting genesis data.");
|
||||
else
|
||||
bulk.clear();
|
||||
|
||||
|
|
@ -197,6 +351,150 @@ bool es_objects_plugin_impl::index_database(const vector<object_id_type>& ids, s
|
|||
else
|
||||
prepareTemplate<asset_bitasset_data_object>(*ba, "bitasset");
|
||||
}
|
||||
} else if (value.is<account_role_object>() && _es_objects_account_role) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const account_role_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "account_role");
|
||||
else
|
||||
prepareTemplate<account_role_object>(*ba, "account_role");
|
||||
}
|
||||
} else if (value.is<committee_member_object>() && _es_objects_committee_member) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const committee_member_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "committee_member");
|
||||
else
|
||||
prepareTemplate<committee_member_object>(*ba, "committee_member");
|
||||
}
|
||||
} else if (value.is<nft_object>() && _es_objects_nft) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const nft_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "nft");
|
||||
else
|
||||
prepareTemplate<nft_object>(*ba, "nft");
|
||||
}
|
||||
} else if (value.is<nft_metadata_object>() && _es_objects_nft) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const nft_metadata_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "nft_metadata");
|
||||
else
|
||||
prepareTemplate<nft_metadata_object>(*ba, "nft_metadata");
|
||||
}
|
||||
} else if (value.is<offer_object>() && _es_objects_nft) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const offer_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "offer");
|
||||
else
|
||||
prepareTemplate<offer_object>(*ba, "offer");
|
||||
}
|
||||
} else if (value.is<sidechain_address_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const sidechain_address_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "sidechain_address");
|
||||
else
|
||||
prepareTemplate<sidechain_address_object>(*ba, "sidechain_address");
|
||||
}
|
||||
} else if (value.is<sidechain_transaction_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const sidechain_transaction_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "sidechain_transaction");
|
||||
else
|
||||
prepareTemplate<sidechain_transaction_object>(*ba, "sidechain_transaction");
|
||||
}
|
||||
} else if (value.is<son_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const son_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "son");
|
||||
else
|
||||
prepareTemplate<son_object>(*ba, "son");
|
||||
}
|
||||
} else if (value.is<son_proposal_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const son_proposal_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "son_proposal");
|
||||
else
|
||||
prepareTemplate<son_proposal_object>(*ba, "son_proposal");
|
||||
}
|
||||
} else if (value.is<son_wallet_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const son_wallet_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "son_wallet");
|
||||
else
|
||||
prepareTemplate<son_wallet_object>(*ba, "son_wallet");
|
||||
}
|
||||
} else if (value.is<son_wallet_deposit_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const son_wallet_deposit_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "son_wallet_deposit");
|
||||
else
|
||||
prepareTemplate<son_wallet_deposit_object>(*ba, "son_wallet_deposit");
|
||||
}
|
||||
} else if (value.is<son_wallet_withdraw_object>() && _es_objects_son) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const son_wallet_withdraw_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "son_wallet_withdraw");
|
||||
else
|
||||
prepareTemplate<son_wallet_withdraw_object>(*ba, "son_wallet_withdraw");
|
||||
}
|
||||
} else if (value.is<transaction_object>() && _es_objects_transaction) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const transaction_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "transaction");
|
||||
else
|
||||
prepareTemplate<transaction_object>(*ba, "transaction");
|
||||
}
|
||||
} else if (value.is<vesting_balance_object>() && _es_objects_vesting_balance) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const vesting_balance_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "vesting_balance");
|
||||
else
|
||||
prepareTemplate<vesting_balance_object>(*ba, "vesting_balance");
|
||||
}
|
||||
} else if (value.is<witness_object>() && _es_objects_witness) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const witness_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "witness");
|
||||
else
|
||||
prepareTemplate<witness_object>(*ba, "witness");
|
||||
}
|
||||
} else if (value.is<worker_object>() && _es_objects_worker) {
|
||||
auto obj = db.find_object(value);
|
||||
auto ba = static_cast<const worker_object *>(obj);
|
||||
if (ba != nullptr) {
|
||||
if (action == "delete")
|
||||
remove_from_database(ba->id, "worker");
|
||||
else
|
||||
prepareTemplate<worker_object>(*ba, "worker");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -296,52 +594,39 @@ void es_objects_plugin::plugin_set_program_options(
|
|||
)
|
||||
{
|
||||
cli.add_options()
|
||||
("es-objects-elasticsearch-url", boost::program_options::value<std::string>(), "Elasticsearch node url(http://localhost:9200/)")
|
||||
("es-objects-elasticsearch-url", boost::program_options::value<std::string>(),
|
||||
"Elasticsearch node url(http://localhost:9200/)")
|
||||
("es-objects-auth", boost::program_options::value<std::string>(), "Basic auth username:password('')")
|
||||
("es-objects-bulk-replay", boost::program_options::value<uint32_t>(), "Number of bulk documents to index on replay(10000)")
|
||||
("es-objects-bulk-sync", boost::program_options::value<uint32_t>(), "Number of bulk documents to index on a synchronized chain(100)")
|
||||
("es-objects-bulk-replay", boost::program_options::value<uint32_t>(),
|
||||
"Number of bulk documents to index on replay(10000)")
|
||||
("es-objects-bulk-sync", boost::program_options::value<uint32_t>(),
|
||||
"Number of bulk documents to index on a synchronized chain(100)")
|
||||
("es-objects-proposals", boost::program_options::value<bool>(), "Store proposal objects(true)")
|
||||
("es-objects-accounts", boost::program_options::value<bool>(), "Store account objects(true)")
|
||||
("es-objects-assets", boost::program_options::value<bool>(), "Store asset objects(true)")
|
||||
("es-objects-balances", boost::program_options::value<bool>(), "Store balances objects(true)")
|
||||
("es-objects-limit-orders", boost::program_options::value<bool>(), "Store limit order objects(true)")
|
||||
("es-objects-asset-bitasset", boost::program_options::value<bool>(), "Store feed data(true)")
|
||||
("es-objects-index-prefix", boost::program_options::value<std::string>(), "Add a prefix to the index(ppobjects-)")
|
||||
("es-objects-keep-only-current", boost::program_options::value<bool>(), "Keep only current state of the objects(true)")
|
||||
("es-objects-start-es-after-block", boost::program_options::value<uint32_t>(), "Start doing ES job after block(0)")
|
||||
("es-objects-limit-orders", boost::program_options::value<bool>(), "Store limit order objects(false)")
|
||||
("es-objects-bitasset", boost::program_options::value<bool>(), "Store feed data(true)")
|
||||
("es-objects-account-role", boost::program_options::value<bool>(), "Store account role objects (true)")
|
||||
("es-objects-committee-member", boost::program_options::value<bool>(), "Store committee member objects(true)")
|
||||
("es-objects-nft", boost::program_options::value<bool>(), "Store nft objects (true)")
|
||||
("es-objects-son", boost::program_options::value<bool>(), "Store son objects (true)")
|
||||
("es-objects-transaction", boost::program_options::value<bool>(), "Store transaction objects (true)")
|
||||
("es-objects-vesting-balance", boost::program_options::value<bool>(), "Store vesting balance objects (true)")
|
||||
("es-objects-witness", boost::program_options::value<bool>(), "Store witness objects (true)")
|
||||
("es-objects-worker", boost::program_options::value<bool>(), "Store worker objects (true)")
|
||||
("es-objects-index-prefix", boost::program_options::value<std::string>(),
|
||||
"Add a prefix to the index(ppobjects-)")
|
||||
("es-objects-keep-only-current", boost::program_options::value<bool>(),
|
||||
"Keep only current state of the objects(true)")
|
||||
("es-objects-start-es-after-block", boost::program_options::value<uint32_t>(),
|
||||
"Start doing ES job after block(0)")
|
||||
;
|
||||
cfg.add(cli);
|
||||
}
|
||||
|
||||
void es_objects_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
database().applied_block.connect([this](const signed_block &b) {
|
||||
if(b.block_num() == 1) {
|
||||
if (!my->genesis())
|
||||
FC_THROW_EXCEPTION(fc::exception, "Error populating genesis data.");
|
||||
}
|
||||
});
|
||||
|
||||
database().new_objects.connect([this]( const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts ) {
|
||||
if(!my->index_database(ids, "create"))
|
||||
{
|
||||
FC_THROW_EXCEPTION(fc::exception, "Error creating object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
database().changed_objects.connect([this]( const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts ) {
|
||||
if(!my->index_database(ids, "update"))
|
||||
{
|
||||
FC_THROW_EXCEPTION(fc::exception, "Error updating object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
database().removed_objects.connect([this](const vector<object_id_type>& ids, const vector<const object*>& objs, const flat_set<account_id_type>& impacted_accounts) {
|
||||
if(!my->index_database(ids, "delete"))
|
||||
{
|
||||
FC_THROW_EXCEPTION(fc::exception, "Error deleting object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (options.count("es-objects-elasticsearch-url")) {
|
||||
my->_es_objects_elasticsearch_url = options["es-objects-elasticsearch-url"].as<std::string>();
|
||||
}
|
||||
|
|
@ -372,6 +657,30 @@ void es_objects_plugin::plugin_initialize(const boost::program_options::variable
|
|||
if (options.count("es-objects-asset-bitasset")) {
|
||||
my->_es_objects_asset_bitasset = options["es-objects-asset-bitasset"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-account-role")) {
|
||||
my->_es_objects_balances = options["es-objects-account-role"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-committee-member")) {
|
||||
my->_es_objects_balances = options["es-objects-committee-member"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-nft")) {
|
||||
my->_es_objects_balances = options["es-objects-nft"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-son")) {
|
||||
my->_es_objects_balances = options["es-objects-son"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-transaction")) {
|
||||
my->_es_objects_balances = options["es-objects-transaction"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-vesting-balance")) {
|
||||
my->_es_objects_balances = options["es-objects-vesting-balance"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-witness")) {
|
||||
my->_es_objects_balances = options["es-objects-witness"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-worker")) {
|
||||
my->_es_objects_balances = options["es-objects-worker"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-index-prefix")) {
|
||||
my->_es_objects_index_prefix = options["es-objects-index-prefix"].as<std::string>();
|
||||
}
|
||||
|
|
@ -381,6 +690,37 @@ void es_objects_plugin::plugin_initialize(const boost::program_options::variable
|
|||
if (options.count("es-objects-start-es-after-block")) {
|
||||
my->_es_objects_start_es_after_block = options["es-objects-start-es-after-block"].as<uint32_t>();
|
||||
}
|
||||
|
||||
database().applied_block.connect([this](const signed_block &b) {
|
||||
if(b.block_num() == 1 && my->_es_objects_start_es_after_block == 0) {
|
||||
if (!my->genesis())
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Error populating genesis data.");
|
||||
}
|
||||
});
|
||||
database().new_objects.connect([this]( const vector<object_id_type>& ids,
|
||||
const flat_set<account_id_type>& impacted_accounts ) {
|
||||
if(!my->index_database(ids, "create"))
|
||||
{
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception,
|
||||
"Error creating object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
database().changed_objects.connect([this]( const vector<object_id_type>& ids,
|
||||
const flat_set<account_id_type>& impacted_accounts ) {
|
||||
if(!my->index_database(ids, "update"))
|
||||
{
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception,
|
||||
"Error updating object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
database().removed_objects.connect([this](const vector<object_id_type>& ids,
|
||||
const vector<const object*>& objs, const flat_set<account_id_type>& impacted_accounts) {
|
||||
if(!my->index_database(ids, "delete"))
|
||||
{
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception,
|
||||
"Error deleting object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void es_objects_plugin::plugin_startup()
|
||||
|
|
@ -396,4 +736,4 @@ void es_objects_plugin::plugin_startup()
|
|||
ilog("elasticsearch OBJECTS: plugin_startup() begin");
|
||||
}
|
||||
|
||||
} }
|
||||
} }
|
||||
|
|
@ -4,7 +4,7 @@ add_library( graphene_generate_genesis
|
|||
generate_genesis.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_generate_genesis graphene_chain graphene_app graphene_time )
|
||||
target_link_libraries( graphene_generate_genesis PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_generate_genesis
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_generate_uia_sharedrop_genesis
|
|||
generate_uia_sharedrop_genesis.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_generate_uia_sharedrop_genesis graphene_chain graphene_app graphene_time )
|
||||
target_link_libraries( graphene_generate_uia_sharedrop_genesis PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_generate_uia_sharedrop_genesis
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -1,303 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Abit More, and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <graphene/grouped_orders/grouped_orders_plugin.hpp>
|
||||
|
||||
#include <graphene/chain/market_object.hpp>
|
||||
|
||||
namespace graphene { namespace grouped_orders {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class grouped_orders_plugin_impl
|
||||
{
|
||||
public:
|
||||
grouped_orders_plugin_impl(grouped_orders_plugin& _plugin)
|
||||
:_self( _plugin ) {}
|
||||
virtual ~grouped_orders_plugin_impl();
|
||||
|
||||
graphene::chain::database& database()
|
||||
{
|
||||
return _self.database();
|
||||
}
|
||||
|
||||
grouped_orders_plugin& _self;
|
||||
flat_set<uint16_t> _tracked_groups;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This secondary index is used to track changes on limit order objects.
|
||||
*/
|
||||
class limit_order_group_index : public secondary_index
|
||||
{
|
||||
public:
|
||||
limit_order_group_index( const flat_set<uint16_t>& groups ) : _tracked_groups( groups ) {};
|
||||
|
||||
virtual void object_inserted( const object& obj ) override;
|
||||
virtual void object_removed( const object& obj ) override;
|
||||
virtual void about_to_modify( const object& before ) override;
|
||||
virtual void object_modified( const object& after ) override;
|
||||
|
||||
const flat_set<uint16_t>& get_tracked_groups() const
|
||||
{ return _tracked_groups; }
|
||||
|
||||
const map< limit_order_group_key, limit_order_group_data >& get_order_groups() const
|
||||
{ return _og_data; }
|
||||
|
||||
private:
|
||||
void remove_order( const limit_order_object& obj, bool remove_empty = true );
|
||||
|
||||
/** tracked groups */
|
||||
flat_set<uint16_t> _tracked_groups;
|
||||
|
||||
/** maps the group key to group data */
|
||||
map< limit_order_group_key, limit_order_group_data > _og_data;
|
||||
};
|
||||
|
||||
void limit_order_group_index::object_inserted( const object& objct )
|
||||
{ try {
|
||||
const limit_order_object& o = static_cast<const limit_order_object&>( objct );
|
||||
|
||||
auto& idx = _og_data;
|
||||
|
||||
for( uint16_t group : get_tracked_groups() )
|
||||
{
|
||||
auto create_ogo = [&]() {
|
||||
idx[ limit_order_group_key( group, o.sell_price ) ] = limit_order_group_data( o.sell_price, o.for_sale );
|
||||
};
|
||||
// if idx is empty, insert this order
|
||||
// Note: not capped
|
||||
if( idx.empty() )
|
||||
{
|
||||
create_ogo();
|
||||
continue;
|
||||
}
|
||||
|
||||
// cap the price
|
||||
price capped_price = o.sell_price;
|
||||
price max = o.sell_price.max();
|
||||
price min = o.sell_price.min();
|
||||
bool capped_max = false;
|
||||
bool capped_min = false;
|
||||
if( o.sell_price > max )
|
||||
{
|
||||
capped_price = max;
|
||||
capped_max = true;
|
||||
}
|
||||
else if( o.sell_price < min )
|
||||
{
|
||||
capped_price = min;
|
||||
capped_min = true;
|
||||
}
|
||||
// if idx is not empty, find the group that is next to this order
|
||||
auto itr = idx.lower_bound( limit_order_group_key( group, capped_price ) );
|
||||
bool check_previous = false;
|
||||
if( itr == idx.end() || itr->first.group != group
|
||||
|| itr->first.min_price.base.asset_id != o.sell_price.base.asset_id
|
||||
|| itr->first.min_price.quote.asset_id != o.sell_price.quote.asset_id )
|
||||
// not same market or group type
|
||||
check_previous = true;
|
||||
else // same market and group type
|
||||
{
|
||||
bool update_max = false;
|
||||
if( capped_price > itr->second.max_price ) // implies itr->min_price <= itr->max_price < max
|
||||
{
|
||||
update_max = true;
|
||||
price max_price = itr->first.min_price * ratio_type( GRAPHENE_100_PERCENT + group, GRAPHENE_100_PERCENT );
|
||||
// max_price should have been capped here
|
||||
if( capped_price > max_price ) // new order is out of range
|
||||
check_previous = true;
|
||||
}
|
||||
if( !check_previous ) // new order is within the range
|
||||
{
|
||||
if( capped_min && o.sell_price < itr->first.min_price )
|
||||
{ // need to update itr->min_price here, if itr is below min, and new order is even lower
|
||||
// TODO improve performance
|
||||
limit_order_group_data data( itr->second.max_price, o.for_sale + itr->second.total_for_sale );
|
||||
idx.erase( itr );
|
||||
idx[ limit_order_group_key( group, o.sell_price ) ] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( update_max || ( capped_max && o.sell_price > itr->second.max_price ) )
|
||||
itr->second.max_price = o.sell_price; // store real price here, not capped
|
||||
itr->second.total_for_sale += o.for_sale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( check_previous )
|
||||
{
|
||||
if( itr == idx.begin() ) // no previous
|
||||
create_ogo();
|
||||
else
|
||||
{
|
||||
--itr; // should be valid
|
||||
if( itr->first.group != group || itr->first.min_price.base.asset_id != o.sell_price.base.asset_id
|
||||
|| itr->first.min_price.quote.asset_id != o.sell_price.quote.asset_id )
|
||||
// not same market or group type
|
||||
create_ogo();
|
||||
else // same market and group type
|
||||
{
|
||||
// due to lower_bound, always true: capped_price < itr->first.min_price, so no need to check again,
|
||||
// if new order is in range of itr group, always need to update itr->first.min_price, unless
|
||||
// o.sell_price is higher than max
|
||||
price min_price = itr->second.max_price / ratio_type( GRAPHENE_100_PERCENT + group, GRAPHENE_100_PERCENT );
|
||||
// min_price should have been capped here
|
||||
if( capped_price < min_price ) // new order is out of range
|
||||
create_ogo();
|
||||
else if( capped_max && o.sell_price >= itr->first.min_price )
|
||||
{ // itr is above max, and price of new order is even higher
|
||||
if( o.sell_price > itr->second.max_price )
|
||||
itr->second.max_price = o.sell_price;
|
||||
itr->second.total_for_sale += o.for_sale;
|
||||
}
|
||||
else
|
||||
{ // new order is within the range
|
||||
// TODO improve performance
|
||||
limit_order_group_data data( itr->second.max_price, o.for_sale + itr->second.total_for_sale );
|
||||
idx.erase( itr );
|
||||
idx[ limit_order_group_key( group, o.sell_price ) ] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (objct) ); }
|
||||
|
||||
void limit_order_group_index::object_removed( const object& objct )
|
||||
{ try {
|
||||
const limit_order_object& o = static_cast<const limit_order_object&>( objct );
|
||||
remove_order( o );
|
||||
} FC_CAPTURE_AND_RETHROW( (objct) ); }
|
||||
|
||||
void limit_order_group_index::about_to_modify( const object& objct )
|
||||
{ try {
|
||||
const limit_order_object& o = static_cast<const limit_order_object&>( objct );
|
||||
remove_order( o, false );
|
||||
} FC_CAPTURE_AND_RETHROW( (objct) ); }
|
||||
|
||||
void limit_order_group_index::object_modified( const object& objct )
|
||||
{ try {
|
||||
object_inserted( objct );
|
||||
} FC_CAPTURE_AND_RETHROW( (objct) ); }
|
||||
|
||||
void limit_order_group_index::remove_order( const limit_order_object& o, bool remove_empty )
|
||||
{
|
||||
auto& idx = _og_data;
|
||||
|
||||
for( uint16_t group : get_tracked_groups() )
|
||||
{
|
||||
// find the group that should contain this order
|
||||
auto itr = idx.lower_bound( limit_order_group_key( group, o.sell_price ) );
|
||||
if( itr == idx.end() || itr->first.group != group
|
||||
|| itr->first.min_price.base.asset_id != o.sell_price.base.asset_id
|
||||
|| itr->first.min_price.quote.asset_id != o.sell_price.quote.asset_id
|
||||
|| itr->second.max_price < o.sell_price )
|
||||
{
|
||||
// can not find corresponding group, should not happen
|
||||
wlog( "can not find the order group containing order for removing (price dismatch): ${o}", ("o",o) );
|
||||
continue;
|
||||
}
|
||||
else // found
|
||||
{
|
||||
if( itr->second.total_for_sale < o.for_sale )
|
||||
// should not happen
|
||||
wlog( "can not find the order group containing order for removing (amount dismatch): ${o}", ("o",o) );
|
||||
else if( !remove_empty || itr->second.total_for_sale > o.for_sale )
|
||||
itr->second.total_for_sale -= o.for_sale;
|
||||
else
|
||||
// it's the only order in the group and need to be removed
|
||||
idx.erase( itr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouped_orders_plugin_impl::~grouped_orders_plugin_impl()
|
||||
{}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
|
||||
grouped_orders_plugin::grouped_orders_plugin() :
|
||||
my( new detail::grouped_orders_plugin_impl(*this) )
|
||||
{
|
||||
}
|
||||
|
||||
grouped_orders_plugin::~grouped_orders_plugin()
|
||||
{
|
||||
}
|
||||
|
||||
std::string grouped_orders_plugin::plugin_name()const
|
||||
{
|
||||
return "grouped_orders";
|
||||
}
|
||||
|
||||
void grouped_orders_plugin::plugin_set_program_options(
|
||||
boost::program_options::options_description& cli,
|
||||
boost::program_options::options_description& cfg
|
||||
)
|
||||
{
|
||||
cli.add_options()
|
||||
("tracked-groups", boost::program_options::value<string>()->default_value("[10,100]"), // 0.1% and 1%
|
||||
"Group orders by percentage increase on price. Specify a JSON array of numbers here, each number is a group, number 1 means 0.01%. ")
|
||||
;
|
||||
cfg.add(cli);
|
||||
}
|
||||
|
||||
void grouped_orders_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{ try {
|
||||
|
||||
if( options.count( "tracked-groups" ) )
|
||||
{
|
||||
const std::string& groups = options["tracked-groups"].as<string>();
|
||||
my->_tracked_groups = fc::json::from_string(groups).as<flat_set<uint16_t>>( 2 );
|
||||
my->_tracked_groups.erase( 0 );
|
||||
}
|
||||
else
|
||||
my->_tracked_groups = fc::json::from_string("[10,100]").as<flat_set<uint16_t>>(2);
|
||||
|
||||
database().add_secondary_index< primary_index<limit_order_index>, detail::limit_order_group_index >( my->_tracked_groups );
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void grouped_orders_plugin::plugin_startup()
|
||||
{
|
||||
}
|
||||
|
||||
const flat_set<uint16_t>& grouped_orders_plugin::tracked_groups() const
|
||||
{
|
||||
return my->_tracked_groups;
|
||||
}
|
||||
|
||||
const map< limit_order_group_key, limit_order_group_data >& grouped_orders_plugin::limit_order_groups()
|
||||
{
|
||||
const auto& idx = database().get_index_type< limit_order_index >();
|
||||
const auto& pidx = dynamic_cast<const primary_index< limit_order_index >&>(idx);
|
||||
const auto& logidx = pidx.get_secondary_index< detail::limit_order_group_index >();
|
||||
return logidx.get_order_groups();
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
@ -4,7 +4,7 @@ add_library( graphene_market_history
|
|||
market_history_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_market_history graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_market_history PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_market_history
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ endif()
|
|||
unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS)
|
||||
unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE)
|
||||
|
||||
target_link_libraries( peerplays_sidechain graphene_chain graphene_app fc zmq )
|
||||
target_link_libraries( peerplays_sidechain PRIVATE graphene_plugin zmq )
|
||||
target_include_directories( peerplays_sidechain
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_script.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_transaction.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin/serialize.hpp>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
#include <graphene/peerplays_sidechain/bitcoin/serialize.hpp>
|
||||
|
||||
#include <fc/io/raw.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/bitcoin/sign_bitcoin_transaction.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain { namespace bitcoin {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,20 @@ namespace detail {
|
|||
class peerplays_sidechain_plugin_impl;
|
||||
}
|
||||
|
||||
struct son_proposal_type {
|
||||
son_proposal_type(int op, son_id_type son, object_id_type object) :
|
||||
op_type(op),
|
||||
son_id(son),
|
||||
object_id(object) {
|
||||
}
|
||||
int op_type;
|
||||
son_id_type son_id;
|
||||
object_id_type object_id;
|
||||
bool operator<(const son_proposal_type &other) const {
|
||||
return std::tie(op_type, son_id, object_id) < std::tie(other.op_type, other.son_id, other.object_id);
|
||||
}
|
||||
};
|
||||
|
||||
class peerplays_sidechain_plugin : public graphene::app::plugin {
|
||||
public:
|
||||
peerplays_sidechain_plugin();
|
||||
|
|
@ -34,6 +48,8 @@ public:
|
|||
bool is_son_deregistered(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
|
||||
void log_son_proposal_retry(int op_type, object_id_type object_id);
|
||||
bool can_son_participate(int op_type, object_id_type object_id);
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ public:
|
|||
bool is_valid_son_proposal(const chain::proposal_object &proposal);
|
||||
fc::ecc::private_key get_private_key(son_id_type son_id);
|
||||
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
|
||||
void log_son_proposal_retry(int op_type, object_id_type object_id);
|
||||
bool can_son_participate(int op_type, object_id_type object_id);
|
||||
|
||||
void schedule_heartbeat_loop();
|
||||
void heartbeat_loop();
|
||||
|
|
@ -75,6 +77,8 @@ private:
|
|||
std::map<chain::public_key_type, fc::ecc::private_key> private_keys;
|
||||
fc::future<void> _heartbeat_task;
|
||||
fc::future<void> _son_processing_task;
|
||||
std::map<son_proposal_type, uint16_t> son_retry_count;
|
||||
uint16_t retries_threshold;
|
||||
|
||||
bool first_block_skipped;
|
||||
void on_applied_block(const signed_block &b);
|
||||
|
|
@ -130,6 +134,7 @@ 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");
|
||||
cfg.add(cli);
|
||||
}
|
||||
|
||||
|
|
@ -138,8 +143,10 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
|
|||
config_ready_son = (options.count("son-id") || options.count("son-ids")) && options.count("peerplays-private-key");
|
||||
if (config_ready_son) {
|
||||
LOAD_VALUE_SET(options, "son-id", sons, chain::son_id_type)
|
||||
if (options.count("son-ids"))
|
||||
boost::insert(sons, fc::json::from_string(options.at("son-ids").as<string>()).as<vector<chain::son_id_type>>(5));
|
||||
if (options.count("son-ids")) {
|
||||
vector<chain::son_id_type> v = fc::json::from_string(options.at("son-ids").as<string>()).as<vector<chain::son_id_type>>(5);
|
||||
sons.insert(v.begin(), v.end());
|
||||
}
|
||||
config_ready_son = config_ready_son && !sons.empty();
|
||||
|
||||
#ifndef ENABLE_MULTIPLE_SONS
|
||||
|
|
@ -167,6 +174,8 @@ 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>();
|
||||
ilog("sidechain-retry-threshold: ${sidechain-retry-threshold}", ("sidechain-retry-threshold", retries_threshold));
|
||||
}
|
||||
if (!config_ready_son) {
|
||||
wlog("Haven't set up SON parameters");
|
||||
|
|
@ -277,7 +286,7 @@ bool peerplays_sidechain_plugin_impl::is_son_deregistered(son_id_type son_id) {
|
|||
if (son_obj == idx.end())
|
||||
return true;
|
||||
|
||||
if(son_obj->status == chain::son_status::deregistered) {
|
||||
if (son_obj->status == chain::son_status::deregistered) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -447,6 +456,22 @@ bool peerplays_sidechain_plugin_impl::is_valid_son_proposal(const chain::proposa
|
|||
return false;
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::log_son_proposal_retry(int op_type, object_id_type object_id) {
|
||||
son_proposal_type prop_type(op_type, get_current_son_id(), object_id);
|
||||
auto itr = son_retry_count.find(prop_type);
|
||||
if (itr != son_retry_count.end()) {
|
||||
itr->second++;
|
||||
} else {
|
||||
son_retry_count[prop_type] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool peerplays_sidechain_plugin_impl::can_son_participate(int op_type, object_id_type object_id) {
|
||||
son_proposal_type prop_type(op_type, get_current_son_id(), object_id);
|
||||
auto itr = son_retry_count.find(prop_type);
|
||||
return (itr == son_retry_count.end() || itr->second < retries_threshold);
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::approve_proposals() {
|
||||
|
||||
auto check_approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_object &proposal) {
|
||||
|
|
@ -693,4 +718,12 @@ fc::ecc::private_key peerplays_sidechain_plugin::get_private_key(chain::public_k
|
|||
return my->get_private_key(public_key);
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::log_son_proposal_retry(int op_type, object_id_type object_id) {
|
||||
my->log_son_proposal_retry(op_type, object_id);
|
||||
}
|
||||
|
||||
bool peerplays_sidechain_plugin::can_son_participate(int op_type, object_id_type object_id) {
|
||||
return my->can_son_participate(op_type, object_id);
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ void sidechain_net_handler::process_proposals() {
|
|||
|
||||
int32_t op_idx_0 = -1;
|
||||
chain::operation op_obj_idx_0;
|
||||
object_id_type object_id;
|
||||
|
||||
if (po->proposed_transaction.operations.size() >= 1) {
|
||||
op_idx_0 = po->proposed_transaction.operations[0].which();
|
||||
|
|
@ -283,6 +284,7 @@ void sidechain_net_handler::process_proposals() {
|
|||
|
||||
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();
|
||||
|
|
@ -292,11 +294,13 @@ void sidechain_net_handler::process_proposals() {
|
|||
switch (op_idx_0) {
|
||||
case chain::operation::tag<chain::son_wallet_update_operation>::value: {
|
||||
should_process = (op_obj_idx_0.get<son_wallet_update_operation>().sidechain == sidechain);
|
||||
object_id = op_obj_idx_0.get<son_wallet_update_operation>().son_wallet_id;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_deposit_process_operation>::value: {
|
||||
son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get<son_wallet_deposit_process_operation>().son_wallet_deposit_id;
|
||||
object_id = swdo_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()) {
|
||||
|
|
@ -307,6 +311,7 @@ void sidechain_net_handler::process_proposals() {
|
|||
|
||||
case chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value: {
|
||||
son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get<son_wallet_withdraw_process_operation>().son_wallet_withdraw_id;
|
||||
object_id = swwo_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()) {
|
||||
|
|
@ -322,6 +327,7 @@ void sidechain_net_handler::process_proposals() {
|
|||
const auto sto = idx.find(st_id);
|
||||
if (sto != idx.end()) {
|
||||
should_process = ((sto->sidechain == sidechain) && (sto->status == sidechain_transaction_status::valid) && signer_expected(*sto, signer));
|
||||
object_id = sto->object_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -332,6 +338,7 @@ void sidechain_net_handler::process_proposals() {
|
|||
const auto sto = idx.find(st_id);
|
||||
if (sto != idx.end()) {
|
||||
should_process = (sto->sidechain == sidechain);
|
||||
object_id = sto->object_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -343,10 +350,14 @@ void sidechain_net_handler::process_proposals() {
|
|||
elog("==================================================");
|
||||
}
|
||||
|
||||
if (should_process) {
|
||||
if (should_process && (op_idx_0 == chain::operation::tag<chain::sidechain_transaction_sign_operation>::value || plugin.can_son_participate(op_idx_0, object_id))) {
|
||||
bool should_approve = process_proposal(*po);
|
||||
if (should_approve) {
|
||||
approve_proposal(po->id, plugin.get_current_son_id());
|
||||
if (approve_proposal(po->id, plugin.get_current_son_id())) {
|
||||
if (op_idx_0 != chain::operation::tag<chain::sidechain_transaction_sign_operation>::value) {
|
||||
plugin.log_son_proposal_retry(op_idx_0, object_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,7 +384,7 @@ void sidechain_net_handler::process_deposits() {
|
|||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, true, false));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const son_wallet_deposit_object &swdo) {
|
||||
if (swdo.id == object_id_type(0, 0, 0)) {
|
||||
if (swdo.id == object_id_type(0, 0, 0) || !plugin.can_son_participate(chain::operation::tag<chain::son_wallet_deposit_process_operation>::value, swdo.id)) {
|
||||
return;
|
||||
}
|
||||
//Ignore the deposits which are not valid anymore, considered refunds.
|
||||
|
|
@ -391,6 +402,7 @@ void sidechain_net_handler::process_deposits() {
|
|||
wlog("Deposit not processed: ${swdo}", ("swdo", swdo));
|
||||
return;
|
||||
}
|
||||
plugin.log_son_proposal_retry(chain::operation::tag<chain::son_wallet_deposit_process_operation>::value, swdo.id);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +415,7 @@ void sidechain_net_handler::process_withdrawals() {
|
|||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, true, false));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const son_wallet_withdraw_object &swwo) {
|
||||
if (swwo.id == object_id_type(0, 0, 0)) {
|
||||
if (swwo.id == object_id_type(0, 0, 0) || !plugin.can_son_participate(chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value, swwo.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -415,6 +427,7 @@ void sidechain_net_handler::process_withdrawals() {
|
|||
wlog("Withdraw not processed: ${swwo}", ("swwo", swwo));
|
||||
return;
|
||||
}
|
||||
plugin.log_son_proposal_retry(chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value, swwo.id);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -513,6 +526,10 @@ void sidechain_net_handler::settle_sidechain_transactions() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!plugin.can_son_participate(chain::operation::tag<chain::sidechain_transaction_settle_operation>::value, sto.object_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ilog("Sidechain transaction to settle: ${sto}", ("sto", sto.id));
|
||||
|
||||
int64_t settle_amount = settle_sidechain_transaction(sto);
|
||||
|
|
@ -559,6 +576,7 @@ void sidechain_net_handler::settle_sidechain_transactions() {
|
|||
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));
|
||||
plugin.log_son_proposal_retry(chain::operation::tag<chain::sidechain_transaction_settle_operation>::value, sto.object_id);
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for sidechain transaction settle operation failed with exception ${e}", ("e", e.what()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1005,6 +1005,7 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
|
|||
|
||||
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();
|
||||
|
|
@ -1107,8 +1108,8 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
|
|||
std::string tx_txid = tx_json.get<std::string>("result.txid");
|
||||
uint32_t tx_confirmations = tx_json.get<uint32_t>("result.confirmations");
|
||||
std::string tx_address = "";
|
||||
int64_t tx_amount = -1;
|
||||
int64_t tx_vout = -1;
|
||||
uint64_t tx_amount = -1;
|
||||
uint64_t tx_vout = -1;
|
||||
|
||||
for (auto &input : tx_json.get_child("result.vout")) {
|
||||
std::string tx_vout_s = input.second.get<std::string>("n");
|
||||
|
|
@ -1286,6 +1287,9 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() {
|
|||
boost::property_tree::ptree active_pw_pt;
|
||||
boost::property_tree::read_json(active_pw_ss, active_pw_pt);
|
||||
if (active_pw_pt.count("error") && active_pw_pt.get_child("error").empty()) {
|
||||
if (!plugin.can_son_participate(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
|
|
@ -1324,6 +1328,7 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() {
|
|||
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));
|
||||
plugin.log_son_proposal_retry(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id);
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what()));
|
||||
return;
|
||||
|
|
@ -1349,6 +1354,7 @@ void sidechain_net_handler_bitcoin::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;
|
||||
if (sao.expires == time_point_sec::maximum()) {
|
||||
auto usr_pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(sao.deposit_public_key)));
|
||||
|
||||
|
|
@ -1374,13 +1380,14 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() {
|
|||
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;
|
||||
retval = true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1658,11 +1665,11 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s
|
|||
std::string pw_address = json.get<std::string>("address");
|
||||
std::string redeem_script = json.get<std::string>("redeemScript");
|
||||
|
||||
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||
uint64_t min_fee_rate = 1000;
|
||||
int64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||
int64_t min_fee_rate = 1000;
|
||||
fee_rate = std::max(fee_rate, min_fee_rate);
|
||||
|
||||
uint64_t total_amount = 0;
|
||||
int64_t total_amount = 0;
|
||||
std::vector<btc_txout> inputs = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0);
|
||||
|
||||
if (inputs.size() == 0) {
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ 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;
|
||||
if (sao.expires == time_point_sec::maximum()) {
|
||||
if (sao.deposit_address == "") {
|
||||
sidechain_address_update_operation op;
|
||||
|
|
@ -150,13 +151,14 @@ void sidechain_net_handler_peerplays::process_sidechain_addresses() {
|
|||
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;
|
||||
retval = true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending transaction for update deposit address operation failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_snapshot
|
|||
snapshot.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_snapshot graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_snapshot PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_snapshot
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_witness
|
|||
witness.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_witness graphene_chain graphene_app )
|
||||
target_link_libraries( graphene_witness PRIVATE graphene_plugin )
|
||||
target_include_directories( graphene_witness
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -91,8 +91,10 @@ void witness_plugin::plugin_initialize(const boost::program_options::variables_m
|
|||
ilog("witness plugin: plugin_initialize() begin");
|
||||
_options = &options;
|
||||
LOAD_VALUE_SET(options, "witness-id", _witnesses, chain::witness_id_type)
|
||||
if (options.count("witness-ids"))
|
||||
boost::insert(_witnesses, fc::json::from_string(options.at("witness-ids").as<string>()).as<vector<chain::witness_id_type>>( 5 ));
|
||||
if (options.count("witness-ids")) {
|
||||
vector<chain::witness_id_type> v = fc::json::from_string(options.at("witness-ids").as<string>()).as<vector<chain::witness_id_type>>( 5 );
|
||||
_witnesses.insert(v.begin(), v.end());
|
||||
}
|
||||
|
||||
if( options.count("private-key") )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ else()
|
|||
endif()
|
||||
|
||||
add_library( graphene_wallet wallet.cpp ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp ${HEADERS} )
|
||||
target_link_libraries( graphene_wallet PRIVATE graphene_app graphene_net graphene_chain graphene_utilities fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( graphene_wallet PRIVATE graphene_app )
|
||||
target_include_directories( graphene_db PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
if(MSVC)
|
||||
|
|
|
|||
|
|
@ -62,13 +62,18 @@ struct brain_key_info
|
|||
public_key_type pub_key;
|
||||
};
|
||||
|
||||
enum authority_type
|
||||
{
|
||||
owner,
|
||||
active
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains the confirmation receipt the sender must give the receiver and
|
||||
* the meta data about the receipt that helps the sender identify which receipt is
|
||||
* for the receiver and which is for the change address.
|
||||
*/
|
||||
struct blind_confirmation
|
||||
struct blind_confirmation
|
||||
{
|
||||
struct output
|
||||
{
|
||||
|
|
@ -307,12 +312,13 @@ class wallet_api
|
|||
*/
|
||||
variant_object about() const;
|
||||
optional<signed_block_with_info> get_block( uint32_t num );
|
||||
vector<optional<signed_block>> get_blocks(uint32_t block_num_from, uint32_t block_num_to)const;
|
||||
/** Returns the number of accounts registered on the blockchain
|
||||
* @returns the number of registered accounts
|
||||
*/
|
||||
uint64_t get_account_count()const;
|
||||
/** Lists all accounts controlled by this wallet.
|
||||
* This returns a list of the full account objects for all accounts whose private keys
|
||||
* This returns a list of the full account objects for all accounts whose private keys
|
||||
* we possess.
|
||||
* @returns a list of account objects
|
||||
*/
|
||||
|
|
@ -324,14 +330,14 @@ class wallet_api
|
|||
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
|
||||
* the last account name returned as the \c lowerbound for the next \c list_accounts() call.
|
||||
*
|
||||
* @param lowerbound the name of the first account to return. If the named account does not exist,
|
||||
* @param lowerbound the name of the first account to return. If the named account does not exist,
|
||||
* the list will start at the account that comes after \c lowerbound
|
||||
* @param limit the maximum number of accounts to return (max: 1000)
|
||||
* @returns a list of accounts mapping account names to account ids
|
||||
*/
|
||||
map<string,account_id_type> list_accounts(const string& lowerbound, uint32_t limit);
|
||||
/** List the balances of an account.
|
||||
* Each account can have multiple balances, one for each type of asset owned by that
|
||||
* Each account can have multiple balances, one for each type of asset owned by that
|
||||
* account. The returned list will only contain assets for which the account has a
|
||||
* nonzero balance
|
||||
* @param id the name or id of the account whose balances you want
|
||||
|
|
@ -339,7 +345,7 @@ class wallet_api
|
|||
*/
|
||||
vector<asset> list_account_balances(const string& id);
|
||||
/** Lists all assets registered on the blockchain.
|
||||
*
|
||||
*
|
||||
* To list all assets, pass the empty string \c "" for the lowerbound to start
|
||||
* at the beginning of the list, and iterate as necessary.
|
||||
*
|
||||
|
|
@ -350,12 +356,12 @@ class wallet_api
|
|||
vector<asset_object> list_assets(const string& lowerbound, uint32_t limit)const;
|
||||
|
||||
/** Returns assets count registered on the blockchain.
|
||||
*
|
||||
*
|
||||
* @returns assets count
|
||||
*/
|
||||
uint64_t get_asset_count()const;
|
||||
|
||||
|
||||
|
||||
|
||||
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
|
||||
unsigned limit = 100,
|
||||
asset_id_type start = asset_id_type() )const;
|
||||
|
|
@ -391,7 +397,7 @@ class wallet_api
|
|||
vector<limit_order_object> get_limit_orders(string a, string b, uint32_t limit)const;
|
||||
vector<call_order_object> get_call_orders(string a, uint32_t limit)const;
|
||||
vector<force_settlement_object> get_settle_orders(string a, uint32_t limit)const;
|
||||
|
||||
|
||||
/** Returns the block chain's slowly-changing settings.
|
||||
* This object contains all of the properties of the blockchain that are fixed
|
||||
* or that change only once per maintenance interval (daily) such as the
|
||||
|
|
@ -447,8 +453,8 @@ class wallet_api
|
|||
* Returns the blockchain object corresponding to the given id.
|
||||
*
|
||||
* This generic function can be used to retrieve any object from the blockchain
|
||||
* that is assigned an ID. Certain types of objects have specialized convenience
|
||||
* functions to return their objects -- e.g., assets have \c get_asset(), accounts
|
||||
* that is assigned an ID. Certain types of objects have specialized convenience
|
||||
* functions to return their objects -- e.g., assets have \c get_asset(), accounts
|
||||
* have \c get_account(), but this function will work for any object.
|
||||
*
|
||||
* @param id the id of the object to return
|
||||
|
|
@ -456,7 +462,7 @@ class wallet_api
|
|||
*/
|
||||
variant get_object(object_id_type id) const;
|
||||
|
||||
/** Returns the current wallet filename.
|
||||
/** Returns the current wallet filename.
|
||||
*
|
||||
* This is the filename that will be used when automatically saving the wallet.
|
||||
*
|
||||
|
|
@ -532,21 +538,21 @@ class wallet_api
|
|||
* @ingroup Wallet Management
|
||||
*/
|
||||
bool is_new()const;
|
||||
|
||||
/** Checks whether the wallet is locked (is unable to use its private keys).
|
||||
|
||||
/** Checks whether the wallet is locked (is unable to use its private keys).
|
||||
*
|
||||
* This state can be changed by calling \c lock() or \c unlock().
|
||||
* @return true if the wallet is locked
|
||||
* @ingroup Wallet Management
|
||||
*/
|
||||
bool is_locked()const;
|
||||
|
||||
|
||||
/** Locks the wallet immediately.
|
||||
* @ingroup Wallet Management
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/** Unlocks the wallet.
|
||||
|
||||
/** Unlocks the wallet.
|
||||
*
|
||||
* The wallet remain unlocked until the \c lock is called
|
||||
* or the program exits.
|
||||
|
|
@ -554,7 +560,7 @@ class wallet_api
|
|||
* @ingroup Wallet Management
|
||||
*/
|
||||
void unlock(string password);
|
||||
|
||||
|
||||
/** Sets a new password on the wallet.
|
||||
*
|
||||
* The wallet must be either 'new' or 'unlocked' to
|
||||
|
|
@ -567,7 +573,7 @@ class wallet_api
|
|||
*
|
||||
* The keys are printed in WIF format. You can import these keys into another wallet
|
||||
* using \c import_key()
|
||||
* @returns a map containing the private keys, indexed by their public key
|
||||
* @returns a map containing the private keys, indexed by their public key
|
||||
*/
|
||||
map<public_key_type, string> dump_private_keys();
|
||||
|
||||
|
|
@ -602,13 +608,13 @@ class wallet_api
|
|||
bool load_wallet_file(string wallet_filename = "");
|
||||
|
||||
/** Quitting from Peerplays wallet.
|
||||
*
|
||||
*
|
||||
* The current wallet will be closed.
|
||||
*/
|
||||
void quit();
|
||||
|
||||
/** Saves the current wallet to the given filename.
|
||||
*
|
||||
*
|
||||
* @warning This does not change the wallet filename that will be used for future
|
||||
* writes, so think of this function as 'Save a Copy As...' instead of
|
||||
* 'Save As...'. Use \c set_wallet_filename() to make the filename
|
||||
|
|
@ -677,7 +683,7 @@ class wallet_api
|
|||
/** Imports the private key for an existing account.
|
||||
*
|
||||
* The private key must match either an owner key or an active key for the
|
||||
* named account.
|
||||
* named account.
|
||||
*
|
||||
* @see dump_private_keys()
|
||||
*
|
||||
|
|
@ -740,6 +746,41 @@ class wallet_api
|
|||
uint32_t referrer_percent,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Updates account public keys
|
||||
*
|
||||
* @param name the name of the existing account
|
||||
* @param old_owner the owner key for the named account to be replaced
|
||||
* @param new_owner the owner key for the named account to be set as new
|
||||
* @param old_active the active key for the named account to be replaced
|
||||
* @param new_active the active key for the named account to be set as new
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction updating account public keys
|
||||
*/
|
||||
signed_transaction update_account_keys(string name,
|
||||
public_key_type old_owner,
|
||||
public_key_type new_owner,
|
||||
public_key_type old_active,
|
||||
public_key_type new_active,
|
||||
bool broadcast = false);
|
||||
|
||||
/**
|
||||
* This method updates the key of an authority for an exisiting account.
|
||||
* Warning: You can create impossible authorities using this method. The method
|
||||
* will fail if you create an impossible owner authority, but will allow impossible
|
||||
* active and posting authorities.
|
||||
*
|
||||
* @param account_name The name of the account whose authority you wish to update
|
||||
* @param type The authority type. e.g. owner or active
|
||||
* @param key The public key to add to the authority
|
||||
* @param weight The weight the key should have in the authority. A weight of 0 indicates the removal of the key.
|
||||
* @param broadcast true if you wish to broadcast the transaction.
|
||||
*/
|
||||
signed_transaction update_account_auth_key(string account_name,
|
||||
authority_type type,
|
||||
public_key_type key,
|
||||
weight_type weight,
|
||||
bool broadcast);
|
||||
|
||||
/**
|
||||
* Upgrades an account to prime status.
|
||||
* This makes the account holder a 'lifetime member'.
|
||||
|
|
@ -780,7 +821,7 @@ class wallet_api
|
|||
* @param to the name or id of the account receiving the funds
|
||||
* @param amount the amount to send (in nominal units -- to send half of a BTS, specify 0.5)
|
||||
* @param asset_symbol the symbol or id of the asset to send
|
||||
* @param memo a memo to attach to the transaction. The memo will be encrypted in the
|
||||
* @param memo a memo to attach to the transaction. The memo will be encrypted in the
|
||||
* transaction and readable for the receiver. There is no length limit
|
||||
* other than the limit imposed by maximum transaction size, but transaction
|
||||
* increase with transaction size
|
||||
|
|
@ -855,7 +896,7 @@ class wallet_api
|
|||
* 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 confirmation_receipt - a base58 encoded stealth confirmation
|
||||
*/
|
||||
blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo );
|
||||
|
||||
|
|
@ -863,18 +904,18 @@ class wallet_api
|
|||
* Transfers a public balance from @from to one or more blinded balances using a
|
||||
* stealth transfer.
|
||||
*/
|
||||
blind_confirmation transfer_to_blind( string from_account_id_or_name,
|
||||
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,
|
||||
vector<pair<string, string>> to_amounts,
|
||||
bool broadcast = false );
|
||||
|
||||
/**
|
||||
* Transfers funds from a set of blinded balances to a public account balance.
|
||||
*/
|
||||
blind_confirmation transfer_from_blind(
|
||||
blind_confirmation transfer_from_blind(
|
||||
string from_blind_account_key_or_label,
|
||||
string to_account_id_or_name,
|
||||
string to_account_id_or_name,
|
||||
string amount,
|
||||
string asset_symbol,
|
||||
bool broadcast = false );
|
||||
|
|
@ -890,14 +931,14 @@ class wallet_api
|
|||
|
||||
/** Place a limit order attempting to sell one asset for another.
|
||||
*
|
||||
* Buying and selling are the same operation on Graphene; if you want to buy BTS
|
||||
* Buying and selling are the same operation on Graphene; if you want to buy BTS
|
||||
* with USD, you should sell USD for BTS.
|
||||
*
|
||||
* The blockchain will attempt to sell the \c symbol_to_sell for as
|
||||
* much \c symbol_to_receive as possible, as long as the price is at
|
||||
* least \c min_to_receive / \c amount_to_sell.
|
||||
* much \c symbol_to_receive as possible, as long as the price is at
|
||||
* least \c min_to_receive / \c amount_to_sell.
|
||||
*
|
||||
* In addition to the transaction fees, market fees will apply as specified
|
||||
* In addition to the transaction fees, market fees will apply as specified
|
||||
* by the issuer of both the selling asset and the receiving asset as
|
||||
* a percentage of the amount exchanged.
|
||||
*
|
||||
|
|
@ -910,16 +951,16 @@ class wallet_api
|
|||
*
|
||||
* @todo Allow order expiration to be set here. Document default/max expiration time
|
||||
*
|
||||
* @param seller_account the account providing the asset being sold, and which will
|
||||
* @param seller_account the account providing the asset being sold, and which will
|
||||
* receive the proceeds of the sale.
|
||||
* @param amount_to_sell the amount of the asset being sold to sell (in nominal units)
|
||||
* @param symbol_to_sell the name or id of the asset to sell
|
||||
* @param min_to_receive the minimum amount you are willing to receive in return for
|
||||
* selling the entire amount_to_sell
|
||||
* @param symbol_to_receive the name or id of the asset you wish to receive
|
||||
* @param timeout_sec if the order does not fill immediately, this is the length of
|
||||
* time the order will remain on the order books before it is
|
||||
* cancelled and the un-spent funds are returned to the seller's
|
||||
* @param timeout_sec if the order does not fill immediately, this is the length of
|
||||
* time the order will remain on the order books before it is
|
||||
* cancelled and the un-spent funds are returned to the seller's
|
||||
* account
|
||||
* @param fill_or_kill if true, the order will only be included in the blockchain
|
||||
* if it is filled immediately; if false, an open order will be
|
||||
|
|
@ -936,12 +977,12 @@ class wallet_api
|
|||
uint32_t timeout_sec = 0,
|
||||
bool fill_or_kill = false,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
/** Place a limit order attempting to sell one asset for another.
|
||||
*
|
||||
*
|
||||
* This API call abstracts away some of the details of the sell_asset call to be more
|
||||
* user friendly. All orders placed with sell never timeout and will not be killed if they
|
||||
* cannot be filled immediately. If you wish for one of these parameters to be different,
|
||||
* cannot be filled immediately. If you wish for one of these parameters to be different,
|
||||
* then sell_asset should be used instead.
|
||||
*
|
||||
* @param seller_account the account providing the asset being sold, and which will
|
||||
|
|
@ -951,7 +992,7 @@ class wallet_api
|
|||
* @param rate The rate in base:quote at which you want to sell.
|
||||
* @param amount The amount of base you want to sell.
|
||||
* @param broadcast true to broadcast the transaction on the network.
|
||||
* @returns The signed transaction selling the funds.
|
||||
* @returns The signed transaction selling the funds.
|
||||
*/
|
||||
signed_transaction sell( string seller_account,
|
||||
string base,
|
||||
|
|
@ -959,7 +1000,7 @@ class wallet_api
|
|||
double rate,
|
||||
double amount,
|
||||
bool broadcast );
|
||||
|
||||
|
||||
/** Place a limit order attempting to buy one asset with another.
|
||||
*
|
||||
* This API call abstracts away some of the details of the sell_asset call to be more
|
||||
|
|
@ -1014,14 +1055,14 @@ class wallet_api
|
|||
* Right now this function is difficult to use because you must provide raw JSON data
|
||||
* structures for the options objects, and those include prices and asset ids.
|
||||
*
|
||||
* @param issuer the name or id of the account who will pay the fee and become the
|
||||
* @param issuer the name or id of the account who will pay the fee and become the
|
||||
* issuer of the new asset. This can be updated later
|
||||
* @param symbol the ticker symbol of the new asset
|
||||
* @param precision the number of digits of precision to the right of the decimal point,
|
||||
* must be less than or equal to 12
|
||||
* @param common asset options required for all new assets.
|
||||
* Note that core_exchange_rate technically needs to store the asset ID of
|
||||
* this new asset. Since this ID is not known at the time this operation is
|
||||
* Note that core_exchange_rate technically needs to store the asset ID of
|
||||
* this new asset. Since this ID is not known at the time this operation is
|
||||
* created, create this price as though the new asset has instance ID 1, and
|
||||
* the chain will overwrite it with the new asset's ID.
|
||||
* @param bitasset_opts options specific to BitAssets. This may be null unless the
|
||||
|
|
@ -1041,7 +1082,7 @@ class wallet_api
|
|||
asset_options common,
|
||||
lottery_asset_options lottery_opts,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
signed_transaction buy_ticket( asset_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy );
|
||||
|
||||
/** Issue new shares of an asset.
|
||||
|
|
@ -1059,8 +1100,8 @@ class wallet_api
|
|||
bool broadcast = false);
|
||||
|
||||
/** Update the core options on an asset.
|
||||
* There are a number of options which all assets in the network use. These options are
|
||||
* enumerated in the asset_object::asset_options struct. This command is used to update
|
||||
* There are a number of options which all assets in the network use. These options are
|
||||
* enumerated in the asset_object::asset_options struct. This command is used to update
|
||||
* these options for an existing asset.
|
||||
*
|
||||
* @note This operation cannot be used to update BitAsset-specific options. For these options,
|
||||
|
|
@ -1124,7 +1165,7 @@ class wallet_api
|
|||
signed_transaction update_asset_feed_producers(string symbol,
|
||||
flat_set<string> new_feed_producers,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
/** Publishes a price feed for the named asset.
|
||||
*
|
||||
* Price feed providers use this command to publish their price feeds for market-issued assets. A price feed is
|
||||
|
|
@ -1152,7 +1193,7 @@ class wallet_api
|
|||
|
||||
/** Pay into the fee pool for the given asset.
|
||||
*
|
||||
* User-issued assets can optionally have a pool of the core asset which is
|
||||
* User-issued assets can optionally have a pool of the core asset which is
|
||||
* automatically used to pay transaction fees for any transaction using that
|
||||
* asset (using the asset's core exchange rate).
|
||||
*
|
||||
|
|
@ -1193,7 +1234,7 @@ class wallet_api
|
|||
* used as backing for other bitassets, those bitassets will be force settled at their current
|
||||
* feed price.
|
||||
*
|
||||
* @note this operation is used only by the asset issuer, \c settle_asset() may be used by
|
||||
* @note this operation is used only by the asset issuer, \c settle_asset() may be used by
|
||||
* any user owning the asset
|
||||
*
|
||||
* @param symbol the name or id of the asset to force settlement on
|
||||
|
|
@ -1261,7 +1302,7 @@ class wallet_api
|
|||
* @returns the signed transaction registering a committee_member
|
||||
*/
|
||||
signed_transaction create_committee_member(string owner_account,
|
||||
string url,
|
||||
string url,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Lists all witnesses registered in the blockchain.
|
||||
|
|
@ -1272,7 +1313,7 @@ class wallet_api
|
|||
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
|
||||
* the last witness name returned as the \c lowerbound for the next \c list_witnesss() call.
|
||||
*
|
||||
* @param lowerbound the name of the first witness to return. If the named witness does not exist,
|
||||
* @param lowerbound the name of the first witness to return. If the named witness does not exist,
|
||||
* the list will start at the witness that comes after \c lowerbound
|
||||
* @param limit the maximum number of witnesss to return (max: 1000)
|
||||
* @returns a list of witnesss mapping witness names to witness ids
|
||||
|
|
@ -1287,7 +1328,7 @@ class wallet_api
|
|||
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
|
||||
* the last committee_member name returned as the \c lowerbound for the next \c list_committee_members() call.
|
||||
*
|
||||
* @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist,
|
||||
* @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist,
|
||||
* the list will start at the committee_member that comes after \c lowerbound
|
||||
* @param limit the maximum number of committee_members to return (max: 1000)
|
||||
* @returns a list of committee_members mapping committee_member names to committee_member ids
|
||||
|
|
@ -1620,7 +1661,7 @@ class wallet_api
|
|||
|
||||
/** Vote for a given committee_member.
|
||||
*
|
||||
* An account can publish a list of all committee_memberes they approve of. This
|
||||
* An account can publish a list of all committee_memberes they approve of. This
|
||||
* command allows you to add or remove committee_memberes from this list.
|
||||
* Each account's vote is weighted according to the number of shares of the
|
||||
* core asset owned by that account at the time the votes are tallied.
|
||||
|
|
@ -1630,7 +1671,7 @@ class wallet_api
|
|||
*
|
||||
* @param voting_account the name or id of the account who is voting with their shares
|
||||
* @param committee_member the name or id of the committee_member' owner account
|
||||
* @param approve true if you wish to vote in favor of that committee_member, false to
|
||||
* @param approve true if you wish to vote in favor of that committee_member, false to
|
||||
* remove your vote in favor of that committee_member
|
||||
* @param broadcast true if you wish to broadcast the transaction
|
||||
* @return the signed transaction changing your vote for the given committee_member
|
||||
|
|
@ -1697,7 +1738,7 @@ class wallet_api
|
|||
|
||||
/** Vote for a given witness.
|
||||
*
|
||||
* An account can publish a list of all witnesses they approve of. This
|
||||
* An account can publish a list of all witnesses they approve of. This
|
||||
* command allows you to add or remove witnesses from this list.
|
||||
* Each account's vote is weighted according to the number of shares of the
|
||||
* core asset owned by that account at the time the votes are tallied.
|
||||
|
|
@ -1707,7 +1748,7 @@ class wallet_api
|
|||
*
|
||||
* @param voting_account the name or id of the account who is voting with their shares
|
||||
* @param witness the name or id of the witness' owner account
|
||||
* @param approve true if you wish to vote in favor of that witness, false to
|
||||
* @param approve true if you wish to vote in favor of that witness, false to
|
||||
* remove your vote in favor of that witness
|
||||
* @param broadcast true if you wish to broadcast the transaction
|
||||
* @return the signed transaction changing your vote for the given witness
|
||||
|
|
@ -1719,12 +1760,12 @@ class wallet_api
|
|||
|
||||
/** Change your witness votes.
|
||||
*
|
||||
* An account can publish a list of all witnesses they approve of.
|
||||
* An account can publish a list of all witnesses they approve of.
|
||||
* Each account's vote is weighted according to the number of shares of the
|
||||
* core asset owned by that account at the time the votes are tallied.
|
||||
* This command allows you to add or remove one or more witnesses from this list
|
||||
* This command allows you to add or remove one or more witnesses from this list
|
||||
* in one call. When you are changing your vote on several witnesses, this
|
||||
* may be easier than multiple `vote_for_witness` and
|
||||
* may be easier than multiple `vote_for_witness` and
|
||||
* `set_desired_witness_and_committee_member_count` calls.
|
||||
*
|
||||
* @note you cannot vote against a witness, you can only vote for the witness
|
||||
|
|
@ -1739,7 +1780,7 @@ class wallet_api
|
|||
* you currently approve). This list can be empty.
|
||||
* @param desired_number_of_witnesses the number of witnesses you believe the network
|
||||
* should have. You must vote for at least this many
|
||||
* witnesses. You can set this to 0 to abstain from
|
||||
* witnesses. You can set this to 0 to abstain from
|
||||
* voting on the number of witnesses.
|
||||
* @param broadcast true if you wish to broadcast the transaction
|
||||
* @return the signed transaction changing your vote for the given witnesses
|
||||
|
|
@ -1770,23 +1811,23 @@ class wallet_api
|
|||
signed_transaction set_voting_proxy(string account_to_modify,
|
||||
optional<string> voting_account,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
/** Set your vote for the number of witnesses and committee_members in the system.
|
||||
*
|
||||
* Each account can voice their opinion on how many committee_members and how many
|
||||
* Each account can voice their opinion on how many committee_members and how many
|
||||
* witnesses there should be in the active committee_member/active witness list. These
|
||||
* are independent of each other. You must vote your approval of at least as many
|
||||
* committee_members or witnesses as you claim there should be (you can't say that there should
|
||||
* be 20 committee_members but only vote for 10).
|
||||
* be 20 committee_members but only vote for 10).
|
||||
*
|
||||
* There are maximum values for each set in the blockchain parameters (currently
|
||||
* There are maximum values for each set in the blockchain parameters (currently
|
||||
* defaulting to 1001).
|
||||
*
|
||||
* This setting can be changed at any time. If your account has a voting proxy
|
||||
* 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 number_of_committee_members the number
|
||||
*
|
||||
* @param broadcast true if you wish to broadcast the transaction
|
||||
* @return the signed transaction changing your vote proxy settings
|
||||
|
|
@ -1839,16 +1880,16 @@ class wallet_api
|
|||
|
||||
/** Returns an uninitialized object representing a given blockchain operation.
|
||||
*
|
||||
* This returns a default-initialized object of the given type; it can be used
|
||||
* This returns a default-initialized object of the given type; it can be used
|
||||
* during early development of the wallet when we don't yet have custom commands for
|
||||
* creating all of the operations the blockchain supports.
|
||||
* creating all of the operations the blockchain supports.
|
||||
*
|
||||
* Any operation the blockchain supports can be created using the transaction builder's
|
||||
* \c add_operation_to_builder_transaction() , but to do that from the CLI you need to
|
||||
* \c add_operation_to_builder_transaction() , but to do that from the CLI you need to
|
||||
* know what the JSON form of the operation looks like. This will give you a template
|
||||
* you can fill in. It's better than nothing.
|
||||
*
|
||||
* @param operation_type the type of operation to return, must be one of the
|
||||
*
|
||||
* @param operation_type the type of operation to return, must be one of the
|
||||
* operations defined in `graphene/chain/operations.hpp`
|
||||
* (e.g., "global_parameters_update_operation")
|
||||
* @return a default-constructed operation of the given type
|
||||
|
|
@ -1873,7 +1914,7 @@ class wallet_api
|
|||
bool broadcast = false);
|
||||
|
||||
/** Propose a fee change.
|
||||
*
|
||||
*
|
||||
* @param proposing_account The account paying the fee to propose the tx
|
||||
* @param expiration_time Timestamp specifying when the proposal will either take effect or expire.
|
||||
* @param changed_values Map of operation type to new fee. Operations may be specified by name or ID.
|
||||
|
|
@ -1915,7 +1956,7 @@ class wallet_api
|
|||
const approval_delta& delta,
|
||||
bool broadcast /* = false */
|
||||
);
|
||||
|
||||
|
||||
order_book get_order_book( const string& base, const string& quote, unsigned limit = 50);
|
||||
|
||||
asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id);
|
||||
|
|
@ -1954,7 +1995,7 @@ class wallet_api
|
|||
sport_id_type sport_id,
|
||||
fc::optional<internationalized_string_type> name,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
signed_transaction propose_delete_sport(
|
||||
const string& proposing_account,
|
||||
fc::time_point_sec expiration_time,
|
||||
|
|
@ -1981,7 +2022,7 @@ class wallet_api
|
|||
fc::time_point_sec expiration_time,
|
||||
event_group_id_type event_group,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
signed_transaction propose_create_event(
|
||||
const string& proposing_account,
|
||||
fc::time_point_sec expiration_time,
|
||||
|
|
@ -2052,7 +2093,7 @@ class wallet_api
|
|||
fc::optional<internationalized_string_type> payout_condition,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Place a bet
|
||||
/** Place a bet
|
||||
* @param bettor the account placing the bet
|
||||
* @param betting_market_id the market on which to bet
|
||||
* @param back_or_lay back or lay
|
||||
|
|
@ -2128,7 +2169,7 @@ class wallet_api
|
|||
tournament_state state);
|
||||
|
||||
/** Get specific information about a tournament
|
||||
* @param tournament_id the ID of the tournament
|
||||
* @param tournament_id the ID of the tournament
|
||||
*/
|
||||
tournament_object get_tournament(tournament_id_type id);
|
||||
|
||||
|
|
@ -2174,6 +2215,7 @@ class wallet_api
|
|||
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_id(custom_permission_id_type permission_id) const;
|
||||
vector<custom_account_authority_object> get_custom_account_authorities_by_permission_name(string owner, string permission_name) const;
|
||||
vector<authority> get_active_custom_account_authorities_by_operation(string owner, int operation_type) const;
|
||||
|
||||
/////////
|
||||
// NFT //
|
||||
/////////
|
||||
|
|
@ -2199,6 +2241,8 @@ class wallet_api
|
|||
bool is_transferable,
|
||||
bool is_sellable,
|
||||
optional<account_role_id_type> role_id,
|
||||
optional<share_type> max_supply,
|
||||
optional<nft_lottery_options> lottery_options,
|
||||
bool broadcast);
|
||||
|
||||
/**
|
||||
|
|
@ -2336,6 +2380,7 @@ class wallet_api
|
|||
* @return Returns vector of NFT objects, empty vector if none
|
||||
*/
|
||||
vector<nft_object> nft_get_all_tokens() const;
|
||||
signed_transaction nft_lottery_buy_ticket( nft_metadata_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy, bool broadcast );
|
||||
|
||||
signed_transaction create_offer(set<nft_id_type> item_ids,
|
||||
string issuer_accound_id_or_name,
|
||||
|
|
@ -2446,6 +2491,8 @@ FC_REFLECT( graphene::wallet::brain_key_info,
|
|||
(pub_key)
|
||||
)
|
||||
|
||||
FC_REFLECT_ENUM( graphene::wallet::authority_type, (owner)(active) )
|
||||
|
||||
FC_REFLECT( graphene::wallet::exported_account_keys, (account_name)(encrypted_private_keys)(public_keys) )
|
||||
|
||||
FC_REFLECT( graphene::wallet::exported_keys, (password_checksum)(account_keys) )
|
||||
|
|
@ -2474,7 +2521,7 @@ FC_REFLECT_DERIVED( graphene::wallet::signed_block_with_info, (graphene::chain::
|
|||
FC_REFLECT_DERIVED( graphene::wallet::vesting_balance_object_with_info, (graphene::chain::vesting_balance_object),
|
||||
(allowed_withdraw)(allowed_withdraw_time) )
|
||||
|
||||
FC_REFLECT( graphene::wallet::operation_detail,
|
||||
FC_REFLECT( graphene::wallet::operation_detail,
|
||||
(memo)(description)(op) )
|
||||
|
||||
FC_API( graphene::wallet::wallet_api,
|
||||
|
|
@ -2509,6 +2556,8 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(derive_owner_keys_from_brain_key)
|
||||
(get_private_key_from_password)
|
||||
(register_account)
|
||||
(update_account_keys)
|
||||
(update_account_auth_key)
|
||||
(upgrade_account)
|
||||
(create_account_with_brain_key)
|
||||
(sell_asset)
|
||||
|
|
@ -2578,6 +2627,7 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(get_account)
|
||||
(get_account_id)
|
||||
(get_block)
|
||||
(get_blocks)
|
||||
(get_account_count)
|
||||
(get_account_history)
|
||||
(get_relative_account_history)
|
||||
|
|
@ -2667,6 +2717,7 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(nft_get_approved)
|
||||
(nft_is_approved_for_all)
|
||||
(nft_get_all_tokens)
|
||||
(nft_lottery_buy_ticket)
|
||||
(create_offer)
|
||||
(create_bid)
|
||||
(cancel_offer)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue