Merge branch master into graphene-updates

This commit is contained in:
Michel Santos 2021-11-09 16:24:26 -05:00
commit 111ac16e92
259 changed files with 233260 additions and 9062 deletions

127
.clang-format Normal file
View file

@ -0,0 +1,127 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -3
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 6
ContinuationIndentWidth: 6
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 3
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 3
UseTab: Never
...

3
.gitignore vendored
View file

@ -11,6 +11,9 @@ moc_*
hardfork.hpp
build_xc
data
CMakeDoxyfile.in
build
build

View file

@ -1,5 +1,9 @@
include:
- template: Code-Quality.gitlab-ci.yml
- template: Dependency-Scanning.gitlab-ci.yml
- template: License-Scanning.gitlab-ci.yml
- template: SAST.gitlab-ci.yml
- template: Secret-Detection.gitlab-ci.yml
stages:
- build
@ -8,26 +12,42 @@ stages:
build:
stage: build
script:
- rm -rf .git/modules/docs .git/modules/libraries/fc ./docs ./libraries/fc
- git submodule sync
- git submodule update --init --recursive
- cmake .
- rm -rf build
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j$(nproc)
artifacts:
untracked: true
paths:
- libraries/
- programs/
- tests/
- build/libraries/
- build/programs/
- build/tests/
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:
dependencies:
- build
script:
- ./tests/betting_test
- ./tests/chain_test
- ./tests/cli_test
- ./build/tests/betting_test --log_level=message
- ./build/tests/chain_test --log_level=message
- ./build/tests/cli_test --log_level=message
tags:
- builder

View file

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

279
CMakeDoxyfile.in Normal file
View file

@ -0,0 +1,279 @@
#
# DO NOT EDIT! THIS FILE WAS GENERATED BY CMAKE!
#
DOXYFILE_ENCODING = @DOXYGEN_DOXYFILE_ENCODING@
PROJECT_NAME = @DOXYGEN_PROJECT_NAME@
PROJECT_NUMBER = @DOXYGEN_PROJECT_NUMBER@
PROJECT_BRIEF = @DOXYGEN_PROJECT_BRIEF@
PROJECT_LOGO = @DOXYGEN_PROJECT_LOGO@
OUTPUT_DIRECTORY = @DOXYGEN_OUTPUT_DIRECTORY@
CREATE_SUBDIRS = @DOXYGEN_CREATE_SUBDIRS@
ALLOW_UNICODE_NAMES = @DOXYGEN_ALLOW_UNICODE_NAMES@
OUTPUT_LANGUAGE = @DOXYGEN_OUTPUT_LANGUAGE@
OUTPUT_TEXT_DIRECTION = @DOXYGEN_OUTPUT_TEXT_DIRECTION@
BRIEF_MEMBER_DESC = @DOXYGEN_BRIEF_MEMBER_DESC@
REPEAT_BRIEF = @DOXYGEN_REPEAT_BRIEF@
ABBREVIATE_BRIEF = @DOXYGEN_ABBREVIATE_BRIEF@
ALWAYS_DETAILED_SEC = @DOXYGEN_ALWAYS_DETAILED_SEC@
INLINE_INHERITED_MEMB = @DOXYGEN_INLINE_INHERITED_MEMB@
FULL_PATH_NAMES = @DOXYGEN_FULL_PATH_NAMES@
STRIP_FROM_PATH = @DOXYGEN_STRIP_FROM_PATH@
STRIP_FROM_INC_PATH = @DOXYGEN_STRIP_FROM_INC_PATH@
SHORT_NAMES = @DOXYGEN_SHORT_NAMES@
JAVADOC_AUTOBRIEF = @DOXYGEN_JAVADOC_AUTOBRIEF@
JAVADOC_BANNER = @DOXYGEN_JAVADOC_BANNER@
QT_AUTOBRIEF = @DOXYGEN_QT_AUTOBRIEF@
MULTILINE_CPP_IS_BRIEF = @DOXYGEN_MULTILINE_CPP_IS_BRIEF@
INHERIT_DOCS = @DOXYGEN_INHERIT_DOCS@
SEPARATE_MEMBER_PAGES = @DOXYGEN_SEPARATE_MEMBER_PAGES@
TAB_SIZE = @DOXYGEN_TAB_SIZE@
ALIASES = @DOXYGEN_ALIASES@
TCL_SUBST = @DOXYGEN_TCL_SUBST@
OPTIMIZE_OUTPUT_FOR_C = @DOXYGEN_OPTIMIZE_OUTPUT_FOR_C@
OPTIMIZE_OUTPUT_JAVA = @DOXYGEN_OPTIMIZE_OUTPUT_JAVA@
OPTIMIZE_FOR_FORTRAN = @DOXYGEN_OPTIMIZE_FOR_FORTRAN@
OPTIMIZE_OUTPUT_VHDL = @DOXYGEN_OPTIMIZE_OUTPUT_VHDL@
OPTIMIZE_OUTPUT_SLICE = @DOXYGEN_OPTIMIZE_OUTPUT_SLICE@
EXTENSION_MAPPING = @DOXYGEN_EXTENSION_MAPPING@
MARKDOWN_SUPPORT = @DOXYGEN_MARKDOWN_SUPPORT@
TOC_INCLUDE_HEADINGS = @DOXYGEN_TOC_INCLUDE_HEADINGS@
AUTOLINK_SUPPORT = @DOXYGEN_AUTOLINK_SUPPORT@
BUILTIN_STL_SUPPORT = @DOXYGEN_BUILTIN_STL_SUPPORT@
CPP_CLI_SUPPORT = @DOXYGEN_CPP_CLI_SUPPORT@
SIP_SUPPORT = @DOXYGEN_SIP_SUPPORT@
IDL_PROPERTY_SUPPORT = @DOXYGEN_IDL_PROPERTY_SUPPORT@
DISTRIBUTE_GROUP_DOC = @DOXYGEN_DISTRIBUTE_GROUP_DOC@
GROUP_NESTED_COMPOUNDS = @DOXYGEN_GROUP_NESTED_COMPOUNDS@
SUBGROUPING = @DOXYGEN_SUBGROUPING@
INLINE_GROUPED_CLASSES = @DOXYGEN_INLINE_GROUPED_CLASSES@
INLINE_SIMPLE_STRUCTS = @DOXYGEN_INLINE_SIMPLE_STRUCTS@
TYPEDEF_HIDES_STRUCT = @DOXYGEN_TYPEDEF_HIDES_STRUCT@
LOOKUP_CACHE_SIZE = @DOXYGEN_LOOKUP_CACHE_SIZE@
EXTRACT_ALL = @DOXYGEN_EXTRACT_ALL@
EXTRACT_PRIVATE = @DOXYGEN_EXTRACT_PRIVATE@
EXTRACT_PRIV_VIRTUAL = @DOXYGEN_EXTRACT_PRIV_VIRTUAL@
EXTRACT_PACKAGE = @DOXYGEN_EXTRACT_PACKAGE@
EXTRACT_STATIC = @DOXYGEN_EXTRACT_STATIC@
EXTRACT_LOCAL_CLASSES = @DOXYGEN_EXTRACT_LOCAL_CLASSES@
EXTRACT_LOCAL_METHODS = @DOXYGEN_EXTRACT_LOCAL_METHODS@
EXTRACT_ANON_NSPACES = @DOXYGEN_EXTRACT_ANON_NSPACES@
HIDE_UNDOC_MEMBERS = @DOXYGEN_HIDE_UNDOC_MEMBERS@
HIDE_UNDOC_CLASSES = @DOXYGEN_HIDE_UNDOC_CLASSES@
HIDE_FRIEND_COMPOUNDS = @DOXYGEN_HIDE_FRIEND_COMPOUNDS@
HIDE_IN_BODY_DOCS = @DOXYGEN_HIDE_IN_BODY_DOCS@
INTERNAL_DOCS = @DOXYGEN_INTERNAL_DOCS@
CASE_SENSE_NAMES = @DOXYGEN_CASE_SENSE_NAMES@
HIDE_SCOPE_NAMES = @DOXYGEN_HIDE_SCOPE_NAMES@
HIDE_COMPOUND_REFERENCE= @DOXYGEN_HIDE_COMPOUND_REFERENCE@
SHOW_INCLUDE_FILES = @DOXYGEN_SHOW_INCLUDE_FILES@
SHOW_GROUPED_MEMB_INC = @DOXYGEN_SHOW_GROUPED_MEMB_INC@
FORCE_LOCAL_INCLUDES = @DOXYGEN_FORCE_LOCAL_INCLUDES@
INLINE_INFO = @DOXYGEN_INLINE_INFO@
SORT_MEMBER_DOCS = @DOXYGEN_SORT_MEMBER_DOCS@
SORT_BRIEF_DOCS = @DOXYGEN_SORT_BRIEF_DOCS@
SORT_MEMBERS_CTORS_1ST = @DOXYGEN_SORT_MEMBERS_CTORS_1ST@
SORT_GROUP_NAMES = @DOXYGEN_SORT_GROUP_NAMES@
SORT_BY_SCOPE_NAME = @DOXYGEN_SORT_BY_SCOPE_NAME@
STRICT_PROTO_MATCHING = @DOXYGEN_STRICT_PROTO_MATCHING@
GENERATE_TODOLIST = @DOXYGEN_GENERATE_TODOLIST@
GENERATE_TESTLIST = @DOXYGEN_GENERATE_TESTLIST@
GENERATE_BUGLIST = @DOXYGEN_GENERATE_BUGLIST@
GENERATE_DEPRECATEDLIST= @DOXYGEN_GENERATE_DEPRECATEDLIST@
ENABLED_SECTIONS = @DOXYGEN_ENABLED_SECTIONS@
MAX_INITIALIZER_LINES = @DOXYGEN_MAX_INITIALIZER_LINES@
SHOW_USED_FILES = @DOXYGEN_SHOW_USED_FILES@
SHOW_FILES = @DOXYGEN_SHOW_FILES@
SHOW_NAMESPACES = @DOXYGEN_SHOW_NAMESPACES@
FILE_VERSION_FILTER = @DOXYGEN_FILE_VERSION_FILTER@
LAYOUT_FILE = @DOXYGEN_LAYOUT_FILE@
CITE_BIB_FILES = @DOXYGEN_CITE_BIB_FILES@
QUIET = @DOXYGEN_QUIET@
WARNINGS = @DOXYGEN_WARNINGS@
WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@
WARN_IF_DOC_ERROR = @DOXYGEN_WARN_IF_DOC_ERROR@
WARN_NO_PARAMDOC = @DOXYGEN_WARN_NO_PARAMDOC@
WARN_AS_ERROR = @DOXYGEN_WARN_AS_ERROR@
WARN_FORMAT = @DOXYGEN_WARN_FORMAT@
WARN_LOGFILE = @DOXYGEN_WARN_LOGFILE@
INPUT = @DOXYGEN_INPUT@
INPUT_ENCODING = @DOXYGEN_INPUT_ENCODING@
FILE_PATTERNS = @DOXYGEN_FILE_PATTERNS@
RECURSIVE = @DOXYGEN_RECURSIVE@
EXCLUDE = @DOXYGEN_EXCLUDE@
EXCLUDE_SYMLINKS = @DOXYGEN_EXCLUDE_SYMLINKS@
EXCLUDE_PATTERNS = @DOXYGEN_EXCLUDE_PATTERNS@
EXCLUDE_SYMBOLS = @DOXYGEN_EXCLUDE_SYMBOLS@
EXAMPLE_PATH = @DOXYGEN_EXAMPLE_PATH@
EXAMPLE_PATTERNS = @DOXYGEN_EXAMPLE_PATTERNS@
EXAMPLE_RECURSIVE = @DOXYGEN_EXAMPLE_RECURSIVE@
IMAGE_PATH = @DOXYGEN_IMAGE_PATH@
INPUT_FILTER = @DOXYGEN_INPUT_FILTER@
FILTER_PATTERNS = @DOXYGEN_FILTER_PATTERNS@
FILTER_SOURCE_FILES = @DOXYGEN_FILTER_SOURCE_FILES@
FILTER_SOURCE_PATTERNS = @DOXYGEN_FILTER_SOURCE_PATTERNS@
USE_MDFILE_AS_MAINPAGE = @DOXYGEN_USE_MDFILE_AS_MAINPAGE@
SOURCE_BROWSER = @DOXYGEN_SOURCE_BROWSER@
INLINE_SOURCES = @DOXYGEN_INLINE_SOURCES@
STRIP_CODE_COMMENTS = @DOXYGEN_STRIP_CODE_COMMENTS@
REFERENCED_BY_RELATION = @DOXYGEN_REFERENCED_BY_RELATION@
REFERENCES_RELATION = @DOXYGEN_REFERENCES_RELATION@
REFERENCES_LINK_SOURCE = @DOXYGEN_REFERENCES_LINK_SOURCE@
SOURCE_TOOLTIPS = @DOXYGEN_SOURCE_TOOLTIPS@
USE_HTAGS = @DOXYGEN_USE_HTAGS@
VERBATIM_HEADERS = @DOXYGEN_VERBATIM_HEADERS@
CLANG_ASSISTED_PARSING = @DOXYGEN_CLANG_ASSISTED_PARSING@
CLANG_OPTIONS = @DOXYGEN_CLANG_OPTIONS@
CLANG_DATABASE_PATH = @DOXYGEN_CLANG_DATABASE_PATH@
ALPHABETICAL_INDEX = @DOXYGEN_ALPHABETICAL_INDEX@
COLS_IN_ALPHA_INDEX = @DOXYGEN_COLS_IN_ALPHA_INDEX@
IGNORE_PREFIX = @DOXYGEN_IGNORE_PREFIX@
GENERATE_HTML = @DOXYGEN_GENERATE_HTML@
HTML_OUTPUT = @DOXYGEN_HTML_OUTPUT@
HTML_FILE_EXTENSION = @DOXYGEN_HTML_FILE_EXTENSION@
HTML_HEADER = @DOXYGEN_HTML_HEADER@
HTML_FOOTER = @DOXYGEN_HTML_FOOTER@
HTML_STYLESHEET = @DOXYGEN_HTML_STYLESHEET@
HTML_EXTRA_STYLESHEET = @DOXYGEN_HTML_EXTRA_STYLESHEET@
HTML_EXTRA_FILES = @DOXYGEN_HTML_EXTRA_FILES@
HTML_COLORSTYLE_HUE = @DOXYGEN_HTML_COLORSTYLE_HUE@
HTML_COLORSTYLE_SAT = @DOXYGEN_HTML_COLORSTYLE_SAT@
HTML_COLORSTYLE_GAMMA = @DOXYGEN_HTML_COLORSTYLE_GAMMA@
HTML_TIMESTAMP = @DOXYGEN_HTML_TIMESTAMP@
HTML_DYNAMIC_MENUS = @DOXYGEN_HTML_DYNAMIC_MENUS@
HTML_DYNAMIC_SECTIONS = @DOXYGEN_HTML_DYNAMIC_SECTIONS@
HTML_INDEX_NUM_ENTRIES = @DOXYGEN_HTML_INDEX_NUM_ENTRIES@
GENERATE_DOCSET = @DOXYGEN_GENERATE_DOCSET@
DOCSET_FEEDNAME = @DOXYGEN_DOCSET_FEEDNAME@
DOCSET_BUNDLE_ID = @DOXYGEN_DOCSET_BUNDLE_ID@
DOCSET_PUBLISHER_ID = @DOXYGEN_DOCSET_PUBLISHER_ID@
DOCSET_PUBLISHER_NAME = @DOXYGEN_DOCSET_PUBLISHER_NAME@
GENERATE_HTMLHELP = @DOXYGEN_GENERATE_HTMLHELP@
CHM_FILE = @DOXYGEN_CHM_FILE@
HHC_LOCATION = @DOXYGEN_HHC_LOCATION@
GENERATE_CHI = @DOXYGEN_GENERATE_CHI@
CHM_INDEX_ENCODING = @DOXYGEN_CHM_INDEX_ENCODING@
BINARY_TOC = @DOXYGEN_BINARY_TOC@
TOC_EXPAND = @DOXYGEN_TOC_EXPAND@
GENERATE_QHP = @DOXYGEN_GENERATE_QHP@
QCH_FILE = @DOXYGEN_QCH_FILE@
QHP_NAMESPACE = @DOXYGEN_QHP_NAMESPACE@
QHP_VIRTUAL_FOLDER = @DOXYGEN_QHP_VIRTUAL_FOLDER@
QHP_CUST_FILTER_NAME = @DOXYGEN_QHP_CUST_FILTER_NAME@
QHP_CUST_FILTER_ATTRS = @DOXYGEN_QHP_CUST_FILTER_ATTRS@
QHP_SECT_FILTER_ATTRS = @DOXYGEN_QHP_SECT_FILTER_ATTRS@
QHG_LOCATION = @DOXYGEN_QHG_LOCATION@
GENERATE_ECLIPSEHELP = @DOXYGEN_GENERATE_ECLIPSEHELP@
ECLIPSE_DOC_ID = @DOXYGEN_ECLIPSE_DOC_ID@
DISABLE_INDEX = @DOXYGEN_DISABLE_INDEX@
GENERATE_TREEVIEW = @DOXYGEN_GENERATE_TREEVIEW@
ENUM_VALUES_PER_LINE = @DOXYGEN_ENUM_VALUES_PER_LINE@
TREEVIEW_WIDTH = @DOXYGEN_TREEVIEW_WIDTH@
EXT_LINKS_IN_WINDOW = @DOXYGEN_EXT_LINKS_IN_WINDOW@
FORMULA_FONTSIZE = @DOXYGEN_FORMULA_FONTSIZE@
FORMULA_TRANSPARENT = @DOXYGEN_FORMULA_TRANSPARENT@
USE_MATHJAX = @DOXYGEN_USE_MATHJAX@
MATHJAX_FORMAT = @DOXYGEN_MATHJAX_FORMAT@
MATHJAX_RELPATH = @DOXYGEN_MATHJAX_RELPATH@
MATHJAX_EXTENSIONS = @DOXYGEN_MATHJAX_EXTENSIONS@
MATHJAX_CODEFILE = @DOXYGEN_MATHJAX_CODEFILE@
SEARCHENGINE = @DOXYGEN_SEARCHENGINE@
SERVER_BASED_SEARCH = @DOXYGEN_SERVER_BASED_SEARCH@
EXTERNAL_SEARCH = @DOXYGEN_EXTERNAL_SEARCH@
SEARCHENGINE_URL = @DOXYGEN_SEARCHENGINE_URL@
SEARCHDATA_FILE = @DOXYGEN_SEARCHDATA_FILE@
EXTERNAL_SEARCH_ID = @DOXYGEN_EXTERNAL_SEARCH_ID@
EXTRA_SEARCH_MAPPINGS = @DOXYGEN_EXTRA_SEARCH_MAPPINGS@
GENERATE_LATEX = @DOXYGEN_GENERATE_LATEX@
LATEX_OUTPUT = @DOXYGEN_LATEX_OUTPUT@
LATEX_CMD_NAME = @DOXYGEN_LATEX_CMD_NAME@
MAKEINDEX_CMD_NAME = @DOXYGEN_MAKEINDEX_CMD_NAME@
LATEX_MAKEINDEX_CMD = @DOXYGEN_LATEX_MAKEINDEX_CMD@
COMPACT_LATEX = @DOXYGEN_COMPACT_LATEX@
PAPER_TYPE = @DOXYGEN_PAPER_TYPE@
EXTRA_PACKAGES = @DOXYGEN_EXTRA_PACKAGES@
LATEX_HEADER = @DOXYGEN_LATEX_HEADER@
LATEX_FOOTER = @DOXYGEN_LATEX_FOOTER@
LATEX_EXTRA_STYLESHEET = @DOXYGEN_LATEX_EXTRA_STYLESHEET@
LATEX_EXTRA_FILES = @DOXYGEN_LATEX_EXTRA_FILES@
PDF_HYPERLINKS = @DOXYGEN_PDF_HYPERLINKS@
USE_PDFLATEX = @DOXYGEN_USE_PDFLATEX@
LATEX_BATCHMODE = @DOXYGEN_LATEX_BATCHMODE@
LATEX_HIDE_INDICES = @DOXYGEN_LATEX_HIDE_INDICES@
LATEX_SOURCE_CODE = @DOXYGEN_LATEX_SOURCE_CODE@
LATEX_BIB_STYLE = @DOXYGEN_LATEX_BIB_STYLE@
LATEX_TIMESTAMP = @DOXYGEN_LATEX_TIMESTAMP@
LATEX_EMOJI_DIRECTORY = @DOXYGEN_LATEX_EMOJI_DIRECTORY@
GENERATE_RTF = @DOXYGEN_GENERATE_RTF@
RTF_OUTPUT = @DOXYGEN_RTF_OUTPUT@
COMPACT_RTF = @DOXYGEN_COMPACT_RTF@
RTF_HYPERLINKS = @DOXYGEN_RTF_HYPERLINKS@
RTF_STYLESHEET_FILE = @DOXYGEN_RTF_STYLESHEET_FILE@
RTF_EXTENSIONS_FILE = @DOXYGEN_RTF_EXTENSIONS_FILE@
RTF_SOURCE_CODE = @DOXYGEN_RTF_SOURCE_CODE@
GENERATE_MAN = @DOXYGEN_GENERATE_MAN@
MAN_OUTPUT = @DOXYGEN_MAN_OUTPUT@
MAN_EXTENSION = @DOXYGEN_MAN_EXTENSION@
MAN_SUBDIR = @DOXYGEN_MAN_SUBDIR@
MAN_LINKS = @DOXYGEN_MAN_LINKS@
GENERATE_XML = @DOXYGEN_GENERATE_XML@
XML_OUTPUT = @DOXYGEN_XML_OUTPUT@
XML_PROGRAMLISTING = @DOXYGEN_XML_PROGRAMLISTING@
XML_NS_MEMB_FILE_SCOPE = @DOXYGEN_XML_NS_MEMB_FILE_SCOPE@
GENERATE_DOCBOOK = @DOXYGEN_GENERATE_DOCBOOK@
DOCBOOK_OUTPUT = @DOXYGEN_DOCBOOK_OUTPUT@
DOCBOOK_PROGRAMLISTING = @DOXYGEN_DOCBOOK_PROGRAMLISTING@
GENERATE_AUTOGEN_DEF = @DOXYGEN_GENERATE_AUTOGEN_DEF@
GENERATE_PERLMOD = @DOXYGEN_GENERATE_PERLMOD@
PERLMOD_LATEX = @DOXYGEN_PERLMOD_LATEX@
PERLMOD_PRETTY = @DOXYGEN_PERLMOD_PRETTY@
PERLMOD_MAKEVAR_PREFIX = @DOXYGEN_PERLMOD_MAKEVAR_PREFIX@
ENABLE_PREPROCESSING = @DOXYGEN_ENABLE_PREPROCESSING@
MACRO_EXPANSION = @DOXYGEN_MACRO_EXPANSION@
EXPAND_ONLY_PREDEF = @DOXYGEN_EXPAND_ONLY_PREDEF@
SEARCH_INCLUDES = @DOXYGEN_SEARCH_INCLUDES@
INCLUDE_PATH = @DOXYGEN_INCLUDE_PATH@
INCLUDE_FILE_PATTERNS = @DOXYGEN_INCLUDE_FILE_PATTERNS@
PREDEFINED = @DOXYGEN_PREDEFINED@
EXPAND_AS_DEFINED = @DOXYGEN_EXPAND_AS_DEFINED@
SKIP_FUNCTION_MACROS = @DOXYGEN_SKIP_FUNCTION_MACROS@
TAGFILES = @DOXYGEN_TAGFILES@
GENERATE_TAGFILE = @DOXYGEN_GENERATE_TAGFILE@
ALLEXTERNALS = @DOXYGEN_ALLEXTERNALS@
EXTERNAL_GROUPS = @DOXYGEN_EXTERNAL_GROUPS@
EXTERNAL_PAGES = @DOXYGEN_EXTERNAL_PAGES@
CLASS_DIAGRAMS = @DOXYGEN_CLASS_DIAGRAMS@
DIA_PATH = @DOXYGEN_DIA_PATH@
HIDE_UNDOC_RELATIONS = @DOXYGEN_HIDE_UNDOC_RELATIONS@
HAVE_DOT = @DOXYGEN_HAVE_DOT@
DOT_NUM_THREADS = @DOXYGEN_DOT_NUM_THREADS@
DOT_FONTNAME = @DOXYGEN_DOT_FONTNAME@
DOT_FONTSIZE = @DOXYGEN_DOT_FONTSIZE@
DOT_FONTPATH = @DOXYGEN_DOT_FONTPATH@
CLASS_GRAPH = @DOXYGEN_CLASS_GRAPH@
COLLABORATION_GRAPH = @DOXYGEN_COLLABORATION_GRAPH@
GROUP_GRAPHS = @DOXYGEN_GROUP_GRAPHS@
UML_LOOK = @DOXYGEN_UML_LOOK@
UML_LIMIT_NUM_FIELDS = @DOXYGEN_UML_LIMIT_NUM_FIELDS@
TEMPLATE_RELATIONS = @DOXYGEN_TEMPLATE_RELATIONS@
INCLUDE_GRAPH = @DOXYGEN_INCLUDE_GRAPH@
INCLUDED_BY_GRAPH = @DOXYGEN_INCLUDED_BY_GRAPH@
CALL_GRAPH = @DOXYGEN_CALL_GRAPH@
CALLER_GRAPH = @DOXYGEN_CALLER_GRAPH@
GRAPHICAL_HIERARCHY = @DOXYGEN_GRAPHICAL_HIERARCHY@
DIRECTORY_GRAPH = @DOXYGEN_DIRECTORY_GRAPH@
DOT_IMAGE_FORMAT = @DOXYGEN_DOT_IMAGE_FORMAT@
INTERACTIVE_SVG = @DOXYGEN_INTERACTIVE_SVG@
DOT_PATH = @DOXYGEN_DOT_PATH@
DOTFILE_DIRS = @DOXYGEN_DOTFILE_DIRS@
MSCFILE_DIRS = @DOXYGEN_MSCFILE_DIRS@
DIAFILE_DIRS = @DOXYGEN_DIAFILE_DIRS@
PLANTUML_JAR_PATH = @DOXYGEN_PLANTUML_JAR_PATH@
PLANTUML_CFG_FILE = @DOXYGEN_PLANTUML_CFG_FILE@
PLANTUML_INCLUDE_PATH = @DOXYGEN_PLANTUML_INCLUDE_PATH@
DOT_GRAPH_MAX_NODES = @DOXYGEN_DOT_GRAPH_MAX_NODES@
MAX_DOT_GRAPH_DEPTH = @DOXYGEN_MAX_DOT_GRAPH_DEPTH@
DOT_TRANSPARENT = @DOXYGEN_DOT_TRANSPARENT@
DOT_MULTI_TARGETS = @DOXYGEN_DOT_MULTI_TARGETS@
GENERATE_LEGEND = @DOXYGEN_GENERATE_LEGEND@
DOT_CLEANUP = @DOXYGEN_DOT_CLEANUP@

View file

@ -135,7 +135,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" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp -Wno-parentheses -Wno-terminate -Wno-invalid-offsetof -Wno-sign-compare" )
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" )

View file

@ -13,6 +13,7 @@ RUN \
build-essential \
ca-certificates \
cmake \
dnsutils \
doxygen \
git \
graphviz \
@ -22,6 +23,7 @@ RUN \
libreadline-dev \
libssl-dev \
libtool \
libzmq3-dev \
locales \
ntp \
pkg-config \
@ -57,7 +59,7 @@ RUN \
cd build/release && \
cmake \
-DBOOST_ROOT="$BOOST_ROOT" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_BUILD_TYPE=Debug \
../.. && \
make witness_node cli_wallet && \
install -s programs/witness_node/witness_node programs/cli_wallet/cli_wallet /usr/local/bin && \

343
Doxyfile
View file

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

View file

@ -7,9 +7,10 @@ This is a quick introduction to get new developers and witnesses up to speed on
The following dependencies were necessary for a clean install of Ubuntu 18.04 LTS:
```
sudo apt-get install gcc-5 g++-5 cmake make libbz2-dev\
libdb++-dev libdb-dev libssl-dev openssl libreadline-dev\
autoconf libtool git
sudo apt-get install autoconf bash build-essential ca-certificates cmake \
doxygen git graphviz libbz2-dev libcurl4-openssl-dev libncurses-dev \
libreadline-dev libssl-dev libtool libzmq3-dev locales ntp pkg-config \
wget
```
## Build Boost 1.67.0
@ -87,14 +88,14 @@ then proceed with:
cmake -DBOOST_ROOT="$BOOST_ROOT" -DCMAKE_BUILD_TYPE=Release .
make
./programs/witness_node/witness_node
Launching the witness creates required directories. Next, **stop the witness** and continue.
$ vi witness_node_data_dir/config.ini
p2p-endpoint = 0.0.0.0:9777
rpc-endpoint = 127.0.0.1:8090
seed-node = 213.184.225.234:59500
Start the witness back up
./programs/witness_node/witness_node
@ -154,7 +155,7 @@ Create your witness (substitute the url for your witness information)
```
create_witness your_witness_username "url" true
```
**Be sure to take note of the block_signing_key**
**Be sure to take note of the block_signing_key**
IMPORTANT (issue below command using block_signing_key just obtained)
```

2
docs

@ -1 +1 @@
Subproject commit 8d8b69d82482101279460fa02f814d0e4030966f
Subproject commit 8df8f66389853df73ab8f6dd73981be2a6957df8

222008
genesis.json

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ add_library( graphene_app
)
# 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_accounts_list graphene_affiliate_stats graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness graphene_bookie graphene_elasticsearch )
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_utilities graphene_debug_witness graphene_bookie graphene_elasticsearch peerplays_sidechain )
target_include_directories( graphene_app
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" )

View file

@ -142,7 +142,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));
@ -182,7 +182,7 @@ namespace graphene { namespace app {
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
{
trx.validate();
_app.chain_database()->check_tansaction_for_duplicated_operations(trx);
_app.chain_database()->check_transaction_for_duplicated_operations(trx);
_app.chain_database()->push_transaction(trx);
if( _app.p2p_node() != nullptr )
_app.p2p_node()->broadcast_transaction(trx);
@ -190,7 +190,7 @@ namespace graphene { namespace app {
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx)
{
_app.chain_database()->check_tansaction_for_duplicated_operations(trx);
_app.chain_database()->check_transaction_for_duplicated_operations(trx);
fc::promise<fc::variant>::ptr prom = fc::promise<fc::variant>::create();
broadcast_transaction_with_callback( [prom]( const fc::variant& v ){
@ -448,7 +448,17 @@ namespace graphene { namespace app {
} case balance_object_type:{
/** these are free from any accounts */
break;
}
} case son_object_type:{
const auto& aobj = dynamic_cast<const son_object*>(obj);
assert( aobj != nullptr );
accounts.insert( aobj->son_account );
break;
} case sidechain_address_object_type:{
const auto& aobj = dynamic_cast<const sidechain_address_object*>(obj);
assert( aobj != nullptr );
accounts.insert( aobj->sidechain_address_account );
break;
}
case sport_object_type:
case event_group_object_type:
case event_object_type:
@ -495,8 +505,8 @@ namespace graphene { namespace app {
assert( aobj != nullptr );
result.push_back( aobj->owner );
break;
} case impl_transaction_object_type:{
const auto& aobj = dynamic_cast<const transaction_object*>(obj);
} case impl_transaction_history_object_type:{
const auto& aobj = dynamic_cast<const transaction_history_object*>(obj);
assert( aobj != nullptr );
flat_set<account_id_type> impacted;
transaction_get_impacted_accounts( aobj->trx, impacted );

View file

@ -162,10 +162,13 @@ namespace detail {
{
// t.me/peerplays #seednodes
vector<string> seeds = {
"ppy-beatrice-seed.blckchnd.com:6666",
"159.69.223.206:7777",
"51.38.237.243:9666",
"pbsa-beatrice.blockchainprojectsbv.com:9195"
"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"
};
for( const string& endpoint_string : seeds )

View file

@ -72,6 +72,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
@ -84,7 +85,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
// Keys
vector<vector<account_id_type>> get_key_references( vector<public_key_type> key )const;
bool is_public_key_registered(string public_key) const;
bool is_public_key_registered(string public_key) const;
// Accounts
account_id_type get_account_id_from_string(const std::string& name_or_id)const;
@ -112,7 +113,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
uint64_t get_asset_count()const;
// Peerplays
vector<sport_object> list_sports() const;
vector<sport_object> list_sports() const;
vector<event_group_object> list_event_groups(sport_id_type sport_id) const;
vector<event_object> list_events_in_group(event_group_id_type event_group_id) const;
vector<betting_market_group_object> list_betting_market_groups(event_id_type) const;
@ -124,14 +125,14 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
unsigned limit = 100,
asset_id_type start = asset_id_type() )const;
vector<asset_object> get_account_lotteries( account_id_type issuer,
vector<asset_object> get_account_lotteries( account_id_type issuer,
asset_id_type stop,
unsigned limit,
asset_id_type start )const;
asset get_lottery_balance( asset_id_type lottery_id )const;
sweeps_vesting_balance_object get_sweeps_vesting_balance_object( account_id_type account )const;
asset get_sweeps_vesting_balance_available_for_claim( account_id_type account )const;
// Markets / feeds
vector<limit_order_object> get_limit_orders( const asset_id_type a, const asset_id_type b, const uint32_t limit )const;
vector<limit_order_object> get_limit_orders( const std::string& a, const std::string& b, const uint32_t limit)const;
@ -156,6 +157,24 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
fc::optional<committee_member_object> get_committee_member_by_account(const std::string account_id_or_name)const;
map<string, committee_member_id_type> lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const;
// SON members
vector<optional<son_object>> get_sons(const vector<son_id_type>& son_ids)const;
fc::optional<son_object> get_son_by_account(account_id_type account)const;
map<string, son_id_type> lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const;
uint64_t get_son_count()const;
// SON wallets
optional<son_wallet_object> get_active_son_wallet();
optional<son_wallet_object> get_son_wallet_by_time_point(time_point_sec time_point);
vector<optional<son_wallet_object>> get_son_wallets(uint32_t limit);
// Sidechain addresses
vector<optional<sidechain_address_object>> get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const;
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_account(account_id_type account)const;
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_sidechain(sidechain_type sidechain)const;
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain)const;
uint64_t get_sidechain_addresses_count()const;
// Votes
vector<variant> lookup_vote_ids( const vector<vote_id_type>& votes )const;
@ -217,6 +236,9 @@ 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;
// Account Role
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
//private:
const account_object* get_account_from_string( const std::string& name_or_id,
bool throw_if_not_found = true ) const;
@ -465,6 +487,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 );
@ -696,7 +733,7 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
const auto& proposal_idx = _db.get_index_type<proposal_index>();
const auto& pidx = dynamic_cast<const base_primary_index&>(proposal_idx);
const auto& proposals_by_account = pidx.get_secondary_index<graphene::chain::required_approval_index>();
std::map<std::string, full_account> results;
for (const std::string& account_name_or_id : names_or_ids)
@ -786,7 +823,7 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
acnt.withdraws.emplace_back(withdraw);
});
auto pending_payouts_range =
auto pending_payouts_range =
_db.get_index_type<pending_dividend_payout_balance_for_holder_object_index>().indices().get<by_account_dividend_payout>().equal_range(boost::make_tuple(account->id));
std::copy(pending_payouts_range.first, pending_payouts_range.second, std::back_inserter(acnt.pending_dividend_payments));
@ -1143,7 +1180,7 @@ vector<asset_object> database_api_impl::get_lotteries( asset_id_type stop,
return result;
}
vector<asset_object> database_api::get_account_lotteries( account_id_type issuer,
vector<asset_object> database_api::get_account_lotteries( account_id_type issuer,
asset_id_type stop,
unsigned limit,
asset_id_type start )const
@ -1151,7 +1188,7 @@ vector<asset_object> database_api::get_account_lotteries( account_id_type issuer
return my->get_account_lotteries( issuer, stop, limit, start );
}
vector<asset_object> database_api_impl::get_account_lotteries( account_id_type issuer,
vector<asset_object> database_api_impl::get_account_lotteries( account_id_type issuer,
asset_id_type stop,
unsigned limit,
asset_id_type start )const
@ -1793,6 +1830,213 @@ map<string, committee_member_id_type> database_api_impl::lookup_committee_member
return committee_members_by_account_name;
}
//////////////////////////////////////////////////////////////////////
// //
// SON members //
// //
//////////////////////////////////////////////////////////////////////
vector<optional<son_object>> database_api::get_sons(const vector<son_id_type>& son_ids)const
{
return my->get_sons( son_ids );
}
vector<optional<son_object>> database_api_impl::get_sons(const vector<son_id_type>& son_ids)const
{
vector<optional<son_object>> result; result.reserve(son_ids.size());
std::transform(son_ids.begin(), son_ids.end(), std::back_inserter(result),
[this](son_id_type id) -> optional<son_object> {
if(auto o = _db.find(id))
return *o;
return {};
});
return result;
}
fc::optional<son_object> database_api::get_son_by_account(account_id_type account)const
{
return my->get_son_by_account( account );
}
fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type account) const
{
const auto& idx = _db.get_index_type<son_index>().indices().get<by_account>();
auto itr = idx.find(account);
if( itr != idx.end() )
return *itr;
return {};
}
map<string, son_id_type> database_api::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const
{
return my->lookup_son_accounts( lower_bound_name, limit );
}
map<string, son_id_type> database_api_impl::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const
{
FC_ASSERT( limit <= 1000 );
const auto& sons_by_id = _db.get_index_type<son_index>().indices().get<by_id>();
// we want to order sons by account name, but that name is in the account object
// so the son_index doesn't have a quick way to access it.
// get all the names and look them all up, sort them, then figure out what
// records to return. This could be optimized, but we expect the
// number of witnesses to be few and the frequency of calls to be rare
std::map<std::string, son_id_type> sons_by_account_name;
for (const son_object& son : sons_by_id)
if (auto account_iter = _db.find(son.son_account))
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
sons_by_account_name.insert(std::make_pair(account_iter->name, son.id));
auto end_iter = sons_by_account_name.begin();
while (end_iter != sons_by_account_name.end() && limit--)
++end_iter;
sons_by_account_name.erase(end_iter, sons_by_account_name.end());
return sons_by_account_name;
}
uint64_t database_api::get_son_count()const
{
return my->get_son_count();
}
uint64_t database_api_impl::get_son_count()const
{
return _db.get_index_type<son_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// SON Wallets //
// //
//////////////////////////////////////////////////////////////////////
optional<son_wallet_object> database_api::get_active_son_wallet()
{
return my->get_active_son_wallet();
}
optional<son_wallet_object> database_api_impl::get_active_son_wallet()
{
const auto& idx = _db.get_index_type<son_wallet_index>().indices().get<by_id>();
auto obj = idx.rbegin();
if (obj != idx.rend()) {
return *obj;
}
return {};
}
optional<son_wallet_object> database_api::get_son_wallet_by_time_point(time_point_sec time_point)
{
return my->get_son_wallet_by_time_point(time_point);
}
optional<son_wallet_object> database_api_impl::get_son_wallet_by_time_point(time_point_sec time_point)
{
const auto& son_wallets_by_id = _db.get_index_type<son_wallet_index>().indices().get<by_id>();
for (const son_wallet_object& swo : son_wallets_by_id) {
if ((time_point >= swo.valid_from) && (time_point < swo.expires))
return swo;
}
return {};
}
vector<optional<son_wallet_object>> database_api::get_son_wallets(uint32_t limit)
{
return my->get_son_wallets(limit);
}
vector<optional<son_wallet_object>> database_api_impl::get_son_wallets(uint32_t limit)
{
FC_ASSERT( limit <= 1000 );
vector<optional<son_wallet_object>> result;
const auto& son_wallets_by_id = _db.get_index_type<son_wallet_index>().indices().get<by_id>();
for (const son_wallet_object& swo : son_wallets_by_id)
result.push_back(swo);
return result;
}
//////////////////////////////////////////////////////////////////////
// //
// Sidechain Accounts //
// //
//////////////////////////////////////////////////////////////////////
vector<optional<sidechain_address_object>> database_api::get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const
{
return my->get_sidechain_addresses( sidechain_address_ids );
}
vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const
{
vector<optional<sidechain_address_object>> result; result.reserve(sidechain_address_ids.size());
std::transform(sidechain_address_ids.begin(), sidechain_address_ids.end(), std::back_inserter(result),
[this](sidechain_address_id_type id) -> optional<sidechain_address_object> {
if(auto o = _db.find(id))
return *o;
return {};
});
return result;
}
vector<optional<sidechain_address_object>> database_api::get_sidechain_addresses_by_account(account_id_type account)const
{
return my->get_sidechain_addresses_by_account( account );
}
vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addresses_by_account(account_id_type account)const
{
vector<optional<sidechain_address_object>> result;
const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_account>().equal_range(account);
std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second,
[&result] (const sidechain_address_object& sao) {
if( sao.expires == time_point_sec::maximum() )
result.push_back(sao);
});
return result;
}
vector<optional<sidechain_address_object>> database_api::get_sidechain_addresses_by_sidechain(sidechain_type sidechain)const
{
return my->get_sidechain_addresses_by_sidechain( sidechain );
}
vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addresses_by_sidechain(sidechain_type sidechain)const
{
vector<optional<sidechain_address_object>> result;
const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_sidechain>().equal_range(sidechain);
std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second,
[&result] (const sidechain_address_object& sao) {
if( sao.expires == time_point_sec::maximum() )
result.push_back(sao);
});
return result;
}
fc::optional<sidechain_address_object> database_api::get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain)const
{
return my->get_sidechain_address_by_account_and_sidechain( account, sidechain );
}
fc::optional<sidechain_address_object> database_api_impl::get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain)const
{
const auto& idx = _db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
auto itr = idx.find( boost::make_tuple( account, sidechain, time_point_sec::maximum() ) );
if( itr != idx.end() )
return *itr;
return {};
}
uint64_t database_api::get_sidechain_addresses_count()const
{
return my->get_sidechain_addresses_count();
}
uint64_t database_api_impl::get_sidechain_addresses_count()const
{
return _db.get_index_type<sidechain_address_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// Votes //
@ -1812,6 +2056,7 @@ vector<variant> database_api_impl::lookup_vote_ids( const vector<vote_id_type>&
const auto& committee_idx = _db.get_index_type<committee_member_index>().indices().get<by_vote_id>();
const auto& for_worker_idx = _db.get_index_type<worker_index>().indices().get<by_vote_for>();
const auto& against_worker_idx = _db.get_index_type<worker_index>().indices().get<by_vote_against>();
const auto& son_idx = _db.get_index_type<son_index>().indices().get<by_vote_id>();
vector<variant> result;
result.reserve( votes.size() );
@ -1854,6 +2099,16 @@ vector<variant> database_api_impl::lookup_vote_ids( const vector<vote_id_type>&
}
break;
}
case vote_id_type::son:
{
auto itr = son_idx.find( id );
if( itr != son_idx.end() )
result.emplace_back( variant( *itr, 5 ) );
else
result.emplace_back( variant() );
break;
}
case vote_id_type::VOTE_TYPE_COUNT: break; // supress unused enum value warnings
default:
FC_CAPTURE_AND_THROW( fc::out_of_range_exception, (id) );
@ -2203,7 +2458,7 @@ vector<tournament_object> database_api::get_tournaments(tournament_id_type stop,
vector<tournament_object> database_api_impl::get_tournaments(tournament_id_type stop,
unsigned limit,
tournament_id_type start)
tournament_id_type start)
{
vector<tournament_object> result;
const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>();
@ -2230,7 +2485,7 @@ vector<tournament_object> database_api_impl::get_tournaments_by_state(tournament
unsigned limit,
tournament_id_type start,
tournament_state state)
{
{
vector<tournament_object> result;
const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>();
for (auto elem: tournament_idx) {
@ -2887,6 +3142,24 @@ vector<offer_history_object> database_api_impl::get_offer_history_by_bidder(cons
return result;
}
vector<account_role_object> database_api::get_account_roles_by_owner(account_id_type owner) const
{
return my->get_account_roles_by_owner(owner);
}
vector<account_role_object> database_api_impl::get_account_roles_by_owner(account_id_type owner) const
{
const auto &idx_aro = _db.get_index_type<account_role_index>().indices().get<by_owner>();
auto idx_aro_range = idx_aro.equal_range(owner);
vector<account_role_object> result;
for (auto itr = idx_aro_range.first; itr != idx_aro_range.second; ++itr)
{
result.push_back(*itr);
}
return result;
}
//////////////////////////////////////////////////////////////////////
// //
// Private methods //
@ -2985,7 +3258,7 @@ void database_api_impl::handle_object_changed(bool force_notify, bool full_objec
/// if a connection hangs then this could get backed up and result in
/// a failure to exit cleanly.
//fc::async([capture_this,this,updates,market_broadcast_queue](){
//if( _subscribe_callback )
//if( _subscribe_callback )
// _subscribe_callback( updates );
for(auto id : ids)

View file

@ -61,8 +61,14 @@ namespace graphene { namespace app {
plug->plugin_set_program_options(plugin_cli_options, plugin_cfg_options);
if( !plugin_cli_options.options().empty() )
_cli_options.add(plugin_cli_options);
if( !plugin_cfg_options.options().empty() )
{
std::string header_name = "plugin-cfg-header-" + plug->plugin_name();
std::string header_desc = plug->plugin_name() + " plugin options";
_cfg_options.add_options()(header_name.c_str(), header_desc.c_str());
_cfg_options.add(plugin_cfg_options);
}
add_available_plugin( plug );
return plug;

View file

@ -0,0 +1,76 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
namespace graphene
{
namespace chain
{
struct custom_account_authority_create_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
custom_permission_id_type permission_id;
int operation_type;
time_point_sec valid_from;
time_point_sec valid_to;
account_id_type owner_account;
extensions_type extensions;
account_id_type fee_payer() const { return owner_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct custom_account_authority_update_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
custom_account_authority_id_type auth_id;
optional<time_point_sec> new_valid_from;
optional<time_point_sec> new_valid_to;
account_id_type owner_account;
extensions_type extensions;
account_id_type fee_payer() const { return owner_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const { return k.fee; }
};
struct custom_account_authority_delete_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
custom_account_authority_id_type auth_id;
account_id_type owner_account;
extensions_type extensions;
account_id_type fee_payer() const { return owner_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const { return k.fee; }
};
} // namespace chain
} // namespace graphene
FC_REFLECT(graphene::chain::custom_account_authority_create_operation::fee_parameters_type, (fee)(price_per_kbyte))
FC_REFLECT(graphene::chain::custom_account_authority_create_operation, (fee)(permission_id)(operation_type)(valid_from)(valid_to)(owner_account)(extensions))
FC_REFLECT(graphene::chain::custom_account_authority_update_operation::fee_parameters_type, (fee))
FC_REFLECT(graphene::chain::custom_account_authority_update_operation, (fee)(auth_id)(new_valid_from)(new_valid_to)(owner_account)(extensions))
FC_REFLECT(graphene::chain::custom_account_authority_delete_operation::fee_parameters_type, (fee))
FC_REFLECT(graphene::chain::custom_account_authority_delete_operation, (fee)(auth_id)(owner_account)(extensions))

View file

@ -0,0 +1,73 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
namespace graphene
{
namespace chain
{
struct custom_permission_create_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type owner_account;
string permission_name;
authority auth;
extensions_type extensions;
account_id_type fee_payer() const { return owner_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct custom_permission_update_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
custom_permission_id_type permission_id;
optional<authority> new_auth;
account_id_type owner_account;
extensions_type extensions;
account_id_type fee_payer() const { return owner_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const { return k.fee; }
};
struct custom_permission_delete_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
custom_permission_id_type permission_id;
account_id_type owner_account;
extensions_type extensions;
account_id_type fee_payer() const { return owner_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const { return k.fee; }
};
} // namespace chain
} // namespace graphene
FC_REFLECT(graphene::chain::custom_permission_create_operation::fee_parameters_type, (fee)(price_per_kbyte))
FC_REFLECT(graphene::chain::custom_permission_create_operation, (fee)(owner_account)(permission_name)(auth)(extensions))
FC_REFLECT(graphene::chain::custom_permission_update_operation::fee_parameters_type, (fee))
FC_REFLECT(graphene::chain::custom_permission_update_operation, (fee)(permission_id)(new_auth)(owner_account)(extensions))
FC_REFLECT(graphene::chain::custom_permission_delete_operation::fee_parameters_type, (fee))
FC_REFLECT(graphene::chain::custom_permission_delete_operation, (fee)(permission_id)(owner_account)(extensions))

View file

@ -43,6 +43,9 @@
#include <graphene/chain/event_object.hpp>
#include <graphene/chain/betting_market_object.hpp>
#include <graphene/chain/global_betting_statistics_object.hpp>
#include <graphene/chain/son_object.hpp>
#include <graphene/chain/son_wallet_object.hpp>
#include <graphene/chain/sidechain_address_object.hpp>
#include <graphene/chain/worker_object.hpp>
#include <graphene/chain/witness_object.hpp>
@ -52,6 +55,7 @@
#include <graphene/chain/custom_account_authority_object.hpp>
#include <graphene/chain/nft_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
@ -195,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.
*/
@ -599,6 +611,102 @@ class database_api
*/
map<string, committee_member_id_type> lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const;
/////////////////
// SON members //
/////////////////
/**
* @brief Get a list of SONs by ID
* @param son_ids IDs of the SONs to retrieve
* @return The SONs corresponding to the provided IDs
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<son_object>> get_sons(const vector<son_id_type>& son_ids)const;
/**
* @brief Get the SON owned by a given account
* @param account The ID of the account whose SON should be retrieved
* @return The SON object, or null if the account does not have a SON
*/
fc::optional<son_object> get_son_by_account(account_id_type account)const;
/**
* @brief Get names and IDs for registered SONs
* @param lower_bound_name Lower bound of the first name to return
* @param limit Maximum number of results to return -- must not exceed 1000
* @return Map of SON names to corresponding IDs
*/
map<string, son_id_type> lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const;
/**
* @brief Get the total number of SONs registered with the blockchain
*/
uint64_t get_son_count()const;
/////////////////////////
// SON Wallets //
/////////////////////////
/**
* @brief Get active SON wallet
* @return Active SON wallet object
*/
optional<son_wallet_object> get_active_son_wallet();
/**
* @brief Get SON wallet that was active for a given time point
* @param time_point Time point
* @return SON wallet object, for the wallet that was active for a given time point
*/
optional<son_wallet_object> get_son_wallet_by_time_point(time_point_sec time_point);
/**
* @brief Get full list of SON wallets
* @param limit Maximum number of results to return
* @return A list of SON wallet objects
*/
vector<optional<son_wallet_object>> get_son_wallets(uint32_t limit);
/////////////////////////
// Sidechain Addresses //
/////////////////////////
/**
* @brief Get a list of sidechain addresses
* @param sidechain_address_ids IDs of the sidechain addresses to retrieve
* @return The sidechain accounts corresponding to the provided IDs
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<sidechain_address_object>> get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const;
/**
* @brief Get the sidechain addresses for a given account
* @param account The ID of the account whose sidechain addresses should be retrieved
* @return The sidechain addresses objects, or null if the account does not have a sidechain addresses
*/
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_account(account_id_type account)const;
/**
* @brief Get the sidechain addresses for a given sidechain
* @param sidechain Sidechain for which addresses should be retrieved
* @return The sidechain addresses objects, or null if the sidechain does not have any addresses
*/
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_sidechain(sidechain_type sidechain)const;
/**
* @brief Get the sidechain addresses for a given account and sidechain
* @param account The ID of the account whose sidechain addresses should be retrieved
* @param sidechain Sidechain for which address should be retrieved
* @return The sidechain addresses objects, or null if the account does not have a sidechain addresses for a given sidechain
*/
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain)const;
/**
* @brief Get the total number of sidechain addresses registered with the blockchain
*/
uint64_t get_sidechain_addresses_count()const;
/// WORKERS
@ -829,7 +937,13 @@ class database_api
vector<offer_history_object> get_offer_history_by_issuer(const offer_history_id_type lower_id, const account_id_type issuer_account_id, uint32_t limit) const;
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;
private:
//////////////////
// ACCOUNT ROLE //
//////////////////
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
private:
std::shared_ptr< database_api_impl > my;
};
@ -859,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)
@ -937,6 +1052,24 @@ FC_API(graphene::app::database_api,
(get_committee_member_by_account)
(lookup_committee_member_accounts)
// SON members
(get_sons)
(get_son_by_account)
(lookup_son_accounts)
(get_son_count)
// SON wallets
(get_active_son_wallet)
(get_son_wallet_by_time_point)
(get_son_wallets)
// Sidechain addresses
(get_sidechain_addresses)
(get_sidechain_addresses_by_account)
(get_sidechain_addresses_by_sidechain)
(get_sidechain_address_by_account_and_sidechain)
(get_sidechain_addresses_count)
// workers
(get_workers_by_account)
// Votes
@ -999,4 +1132,7 @@ FC_API(graphene::app::database_api,
(get_offer_history_by_issuer)
(get_offer_history_by_item)
(get_offer_history_by_bidder)
// Account Roles
(get_account_roles_by_owner)
)

View file

@ -72,6 +72,5 @@ FC_REFLECT( graphene::app::full_account,
(proposals)
(assets)
(withdraws)
(proposals)
(pending_dividend_payments)
)

View file

@ -0,0 +1,148 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/types.hpp>
namespace graphene { namespace chain {
struct nft_metadata_create_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type owner;
std::string name;
std::string symbol;
std::string base_uri;
optional<account_id_type> revenue_partner;
optional<uint16_t> revenue_split;
bool is_transferable = false;
bool is_sellable = true;
// Accounts Role
optional<account_role_id_type> account_role;
extensions_type extensions;
account_id_type fee_payer()const { return owner; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct nft_metadata_update_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type owner;
nft_metadata_id_type nft_metadata_id;
optional<std::string> name;
optional<std::string> symbol;
optional<std::string> base_uri;
optional<account_id_type> revenue_partner;
optional<uint16_t> revenue_split;
optional<bool> is_transferable;
optional<bool> is_sellable;
// Accounts Role
optional<account_role_id_type> account_role;
extensions_type extensions;
account_id_type fee_payer()const { return owner; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct nft_mint_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type payer;
nft_metadata_id_type nft_metadata_id;
account_id_type owner;
account_id_type approved;
vector<account_id_type> approved_operators;
std::string token_uri;
extensions_type extensions;
account_id_type fee_payer()const { return payer; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct nft_safe_transfer_from_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type operator_;
account_id_type from;
account_id_type to;
nft_id_type token_id;
string data;
extensions_type extensions;
account_id_type fee_payer()const { return operator_; }
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct nft_approve_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
asset fee;
account_id_type operator_;
account_id_type approved;
nft_id_type token_id;
extensions_type extensions;
account_id_type fee_payer()const { return operator_; }
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct nft_set_approval_for_all_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
asset fee;
account_id_type owner;
account_id_type operator_;
bool approved;
extensions_type extensions;
account_id_type fee_payer()const { return owner; }
share_type calculate_fee(const fee_parameters_type &k) const;
};
} } // graphene::chain
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) )
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation::fee_parameters_type, (fee) (price_per_kbyte) )
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_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) )
FC_REFLECT( graphene::chain::nft_approve_operation, (fee) (operator_) (approved) (token_id) (extensions) )
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (owner) (operator_) (approved) (extensions) )

View file

@ -0,0 +1,143 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/memo.hpp>
namespace graphene
{
namespace chain
{
/*
* @class offer_operation
* @brief To place an offer to buy or sell an item, a user broadcasts a
* proposed transaction
* @ingroup operations
* operation
*/
struct offer_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION; /// only required for large memos.
};
asset fee;
set<nft_id_type> item_ids;
// /**
// * minimum_price.asset_id == maximum_price.asset_id.
// * to set fixed price without auction minimum_price == maximum_price
// * If buying_item is true, and minimum_price != maximum_price, the user is
// proposing a “reverse auction”
// * where bidders can offer to sell the item for progressively lower prices.
// * In this case, minimum_price functions as the sell-it-now price for the
// reverse auction
// */
account_id_type issuer;
/// minimum_price is minimum bid price. 0 if no minimum_price required
asset minimum_price;
/// buy_it_now price. 0 if no maximum price
asset maximum_price;
/// true means user wants to buy item, false mean user is selling item
bool buying_item;
/// not transaction expiration date
fc::time_point_sec offer_expiration_date;
/// User provided data encrypted to the memo key of the "to" account
optional<memo_data> memo;
extensions_type extensions;
account_id_type fee_payer() const { return issuer; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct bid_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type bidder;
asset bid_price;
offer_id_type offer_id;
extensions_type extensions;
account_id_type fee_payer() const { return bidder; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
struct cancel_offer_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
};
asset fee;
account_id_type issuer;
offer_id_type offer_id;
extensions_type extensions;
account_id_type fee_payer() const { return issuer; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
enum class result_type
{
Expired = 0,
ExpiredNoBid = 1,
Cancelled = 2
};
struct finalize_offer_operation : public base_operation
{
struct fee_parameters_type
{
uint64_t fee = 0;
};
asset fee;
account_id_type fee_paying_account;
offer_id_type offer_id;
result_type result;
extensions_type extensions;
account_id_type fee_payer() const { return fee_paying_account; }
void validate() const;
share_type calculate_fee(const fee_parameters_type &k) const;
};
} // namespace chain
} // namespace graphene
FC_REFLECT(graphene::chain::offer_operation::fee_parameters_type,
(fee)(price_per_kbyte));
FC_REFLECT(graphene::chain::offer_operation,
(fee)(item_ids)(issuer)(minimum_price)(maximum_price)(buying_item)(offer_expiration_date)(memo)(extensions));
FC_REFLECT(graphene::chain::bid_operation::fee_parameters_type,
(fee));
FC_REFLECT(graphene::chain::bid_operation,
(fee)(bidder)(bid_price)(offer_id)(extensions));
FC_REFLECT(graphene::chain::cancel_offer_operation::fee_parameters_type,
(fee));
FC_REFLECT(graphene::chain::cancel_offer_operation,
(fee)(issuer)(offer_id)(extensions));
FC_REFLECT_ENUM(graphene::chain::result_type, (Expired)(ExpiredNoBid)(Cancelled));
FC_REFLECT(graphene::chain::finalize_offer_operation::fee_parameters_type,
(fee));
FC_REFLECT(graphene::chain::finalize_offer_operation,
(fee)(fee_paying_account)(offer_id)(result)(extensions));

View file

@ -0,0 +1,80 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/sidechain_defs.hpp>
namespace graphene { namespace chain {
struct sidechain_address_add_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
account_id_type sidechain_address_account;
sidechain_type sidechain;
string deposit_public_key;
string deposit_address;
string deposit_address_data;
string withdraw_public_key;
string withdraw_address;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct sidechain_address_update_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
sidechain_address_id_type sidechain_address_id;
account_id_type sidechain_address_account;
sidechain_type sidechain;
optional<string> deposit_public_key;
optional<string> deposit_address;
optional<string> deposit_address_data;
optional<string> withdraw_public_key;
optional<string> withdraw_address;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct sidechain_address_delete_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
sidechain_address_id_type sidechain_address_id;
account_id_type sidechain_address_account;
sidechain_type sidechain;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
} } // namespace graphene::chain
FC_REFLECT(graphene::chain::sidechain_address_add_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::sidechain_address_add_operation, (fee)(payer)
(sidechain_address_account)(sidechain)
(deposit_public_key)(deposit_address)(deposit_address_data)
(withdraw_public_key)(withdraw_address) )
FC_REFLECT(graphene::chain::sidechain_address_update_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::sidechain_address_update_operation, (fee)(payer)
(sidechain_address_id)
(sidechain_address_account)(sidechain)
(deposit_public_key)(deposit_address)(deposit_address_data)
(withdraw_public_key)(withdraw_address) )
FC_REFLECT(graphene::chain::sidechain_address_delete_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::sidechain_address_delete_operation, (fee)(payer)
(sidechain_address_id)
(sidechain_address_account)(sidechain) )

View file

@ -0,0 +1,88 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/protocol/types.hpp>
#include <graphene/chain/sidechain_defs.hpp>
#include <graphene/chain/son_info.hpp>
namespace graphene { namespace chain {
struct sidechain_transaction_create_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
sidechain_type sidechain;
object_id_type object_id;
std::string transaction;
std::vector<son_info> signers;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct sidechain_transaction_sign_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
son_id_type signer;
account_id_type payer;
sidechain_transaction_id_type sidechain_transaction_id;
std::string signature;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee( const fee_parameters_type& k )const { return 0; }
};
struct sidechain_transaction_send_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
sidechain_transaction_id_type sidechain_transaction_id;
std::string sidechain_transaction;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee( const fee_parameters_type& k )const { return 0; }
};
struct sidechain_transaction_settle_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
sidechain_transaction_id_type sidechain_transaction_id;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee( const fee_parameters_type& k )const { return 0; }
};
} } // graphene::chain
FC_REFLECT( graphene::chain::sidechain_transaction_create_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::sidechain_transaction_create_operation, (fee)(payer)
(sidechain)
(object_id)
(transaction)
(signers) )
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation, (fee)(signer)(payer)
(sidechain_transaction_id)
(signature) )
FC_REFLECT( graphene::chain::sidechain_transaction_send_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::sidechain_transaction_send_operation, (fee)(payer)
(sidechain_transaction_id)
(sidechain_transaction) )
FC_REFLECT( graphene::chain::sidechain_transaction_settle_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::sidechain_transaction_settle_operation, (fee)(payer)
(sidechain_transaction_id) )

View file

@ -0,0 +1,119 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/sidechain_defs.hpp>
namespace graphene { namespace chain {
struct son_create_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type owner_account;
std::string url;
vesting_balance_id_type deposit;
public_key_type signing_key;
flat_map<sidechain_type, string> sidechain_public_keys;
vesting_balance_id_type pay_vb;
account_id_type fee_payer()const { return owner_account; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_update_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
son_id_type son_id;
account_id_type owner_account;
optional<std::string> new_url;
optional<vesting_balance_id_type> new_deposit;
optional<public_key_type> new_signing_key;
optional<flat_map<sidechain_type, string>> new_sidechain_public_keys;
optional<vesting_balance_id_type> new_pay_vb;
account_id_type fee_payer()const { return owner_account; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_deregister_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
son_id_type son_id;
account_id_type payer;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_heartbeat_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
son_id_type son_id;
account_id_type owner_account;
time_point_sec ts;
account_id_type fee_payer()const { return owner_account; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_report_down_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
son_id_type son_id;
account_id_type payer;
time_point_sec down_ts;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
enum class son_maintenance_request_type
{
request_maintenance,
cancel_request_maintenance
};
struct son_maintenance_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
son_id_type son_id;
account_id_type owner_account;
son_maintenance_request_type request_type = son_maintenance_request_type::request_maintenance;
account_id_type fee_payer()const { return owner_account; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
} } // namespace graphene::chain
FC_REFLECT(graphene::chain::son_create_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_create_operation, (fee)(owner_account)(url)(deposit)(signing_key)(sidechain_public_keys)
(pay_vb) )
FC_REFLECT(graphene::chain::son_update_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_update_operation, (fee)(son_id)(owner_account)(new_url)(new_deposit)
(new_signing_key)(new_sidechain_public_keys)(new_pay_vb) )
FC_REFLECT(graphene::chain::son_deregister_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_deregister_operation, (fee)(son_id)(payer) )
FC_REFLECT(graphene::chain::son_heartbeat_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_heartbeat_operation, (fee)(son_id)(owner_account)(ts) )
FC_REFLECT(graphene::chain::son_report_down_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_report_down_operation, (fee)(son_id)(payer)(down_ts) )
FC_REFLECT_ENUM( graphene::chain::son_maintenance_request_type, (request_maintenance)(cancel_request_maintenance) )
FC_REFLECT(graphene::chain::son_maintenance_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_maintenance_operation, (fee)(son_id)(owner_account)(request_type) )

View file

@ -0,0 +1,40 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/son_info.hpp>
namespace graphene { namespace chain {
struct son_wallet_recreate_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
vector<son_info> sons;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_wallet_update_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
son_wallet_id_type son_wallet_id;
sidechain_type sidechain;
string address;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
} } // namespace graphene::chain
FC_REFLECT(graphene::chain::son_wallet_recreate_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_wallet_recreate_operation, (fee)(payer)(sons) )
FC_REFLECT(graphene::chain::son_wallet_update_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_wallet_update_operation, (fee)(payer)(son_wallet_id)(sidechain)(address) )

View file

@ -0,0 +1,57 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/sidechain_defs.hpp>
#include <fc/safe.hpp>
namespace graphene { namespace chain {
struct son_wallet_deposit_create_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
son_id_type son_id;
fc::time_point_sec timestamp;
uint32_t block_num;
sidechain_type sidechain;
std::string sidechain_uid;
std::string sidechain_transaction_id;
std::string sidechain_from;
std::string sidechain_to;
std::string sidechain_currency;
fc::safe<int64_t> sidechain_amount;
chain::account_id_type peerplays_from;
chain::account_id_type peerplays_to;
chain::asset peerplays_asset;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_wallet_deposit_process_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
son_wallet_deposit_id_type son_wallet_deposit_id;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
} } // namespace graphene::chain
FC_REFLECT(graphene::chain::son_wallet_deposit_create_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_wallet_deposit_create_operation, (fee)(payer)
(son_id) (timestamp) (block_num) (sidechain)
(sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_currency) (sidechain_amount)
(peerplays_from) (peerplays_to) (peerplays_asset) )
FC_REFLECT(graphene::chain::son_wallet_deposit_process_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_wallet_deposit_process_operation, (fee)(payer)
(son_wallet_deposit_id) )

View file

@ -0,0 +1,56 @@
#pragma once
#include <graphene/chain/protocol/base.hpp>
#include <graphene/chain/sidechain_defs.hpp>
#include <fc/safe.hpp>
namespace graphene { namespace chain {
struct son_wallet_withdraw_create_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
son_id_type son_id;
fc::time_point_sec timestamp;
uint32_t block_num;
sidechain_type sidechain;
std::string peerplays_uid;
std::string peerplays_transaction_id;
chain::account_id_type peerplays_from;
chain::asset peerplays_asset;
sidechain_type withdraw_sidechain;
std::string withdraw_address;
std::string withdraw_currency;
safe<int64_t> withdraw_amount;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
struct son_wallet_withdraw_process_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 0; };
asset fee;
account_id_type payer;
son_wallet_withdraw_id_type son_wallet_withdraw_id;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
};
} } // namespace graphene::chain
FC_REFLECT(graphene::chain::son_wallet_withdraw_create_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_wallet_withdraw_create_operation, (fee)(payer)
(son_id) (timestamp) (block_num) (sidechain)
(peerplays_uid) (peerplays_transaction_id) (peerplays_from) (peerplays_asset)
(withdraw_sidechain) (withdraw_address) (withdraw_currency) (withdraw_amount) )
FC_REFLECT(graphene::chain::son_wallet_withdraw_process_operation::fee_parameters_type, (fee) )
FC_REFLECT(graphene::chain::son_wallet_withdraw_process_operation, (fee)(payer)
(son_wallet_withdraw_id) )

14
libraries/chain/CMakeLists.txt Normal file → Executable file
View file

@ -89,6 +89,20 @@ add_library( graphene_chain
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
${HEADERS}
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
)

View file

@ -108,6 +108,8 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio
}
if( d.head_block_time() < HARDFORK_999_TIME )
FC_ASSERT( !op.extensions.value.affiliate_distributions.valid(), "Affiliate reward distributions not allowed yet" );
if (d.head_block_time() < HARDFORK_SON_TIME)
FC_ASSERT(op.name != "son-account", "Son account creation before SON hardfork");
FC_ASSERT( fee_paying_account->is_lifetime_member(), "Only Lifetime members may register an account." );
FC_ASSERT( op.referrer(d).is_member(d.head_block_time()), "The referrer must be either a lifetime or annual subscriber." );

View file

@ -0,0 +1,162 @@
#include <graphene/chain/account_role_evaluator.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/chain/hardfork.hpp>
#include <graphene/chain/rbac_hardfork_visitor.hpp>
namespace graphene
{
namespace chain
{
void_result account_role_create_evaluator::do_evaluate(const account_role_create_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.owner(d);
rbac_operation_hardfork_visitor arvtor(now);
for (const auto &op_type : op.allowed_operations)
{
arvtor(op_type);
}
for (const auto &acc : op.whitelisted_accounts)
{
acc(d);
}
FC_ASSERT(op.valid_to > now, "valid_to expiry should be in future");
FC_ASSERT((op.valid_to - now) <= fc::seconds(d.get_global_properties().parameters.account_roles_max_lifetime()), "Validity of the account role beyond max expiry");
const auto &ar_idx = d.get_index_type<account_role_index>().indices().get<by_owner>();
auto aro_range = ar_idx.equal_range(op.owner);
FC_ASSERT(std::distance(aro_range.first, aro_range.second) < d.get_global_properties().parameters.account_roles_max_per_account(), "Max account roles that can be created by one owner is reached");
return void_result();
}
FC_CAPTURE_AND_RETHROW((op))
}
object_id_type account_role_create_evaluator::do_apply(const account_role_create_operation &op)
{
try
{
database &d = db();
return d.create<account_role_object>([&op](account_role_object &obj) mutable {
obj.owner = op.owner;
obj.name = op.name;
obj.metadata = op.metadata;
obj.allowed_operations = op.allowed_operations;
obj.whitelisted_accounts = op.whitelisted_accounts;
obj.valid_to = op.valid_to;
})
.id;
}
FC_CAPTURE_AND_RETHROW((op))
}
void_result account_role_update_evaluator::do_evaluate(const account_role_update_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.owner(d);
const account_role_object &aobj = op.account_role_id(d);
FC_ASSERT(aobj.owner == op.owner, "Only owner account can update account role object");
for (const auto &op_type : op.allowed_operations_to_remove)
{
FC_ASSERT(aobj.allowed_operations.find(op_type) != aobj.allowed_operations.end(),
"Cannot remove non existent operation");
}
for (const auto &acc : op.accounts_to_remove)
{
FC_ASSERT(aobj.whitelisted_accounts.find(acc) != aobj.whitelisted_accounts.end(),
"Cannot remove non existent account");
}
rbac_operation_hardfork_visitor arvtor(now);
for (const auto &op_type : op.allowed_operations_to_add)
{
arvtor(op_type);
}
FC_ASSERT((aobj.allowed_operations.size() + op.allowed_operations_to_add.size() - op.allowed_operations_to_remove.size()) > 0, "Allowed operations should be positive");
for (const auto &acc : op.accounts_to_add)
{
acc(d);
}
FC_ASSERT((aobj.whitelisted_accounts.size() + op.accounts_to_add.size() - op.accounts_to_remove.size()) > 0, "Accounts should be positive");
if (op.valid_to)
{
FC_ASSERT(*op.valid_to > now, "valid_to expiry should be in future");
FC_ASSERT((*op.valid_to - now) <= fc::seconds(d.get_global_properties().parameters.account_roles_max_lifetime()), "Validity of the account role beyond max expiry");
}
return void_result();
}
FC_CAPTURE_AND_RETHROW((op))
}
void_result account_role_update_evaluator::do_apply(const account_role_update_operation &op)
{
try
{
database &d = db();
const account_role_object &aobj = op.account_role_id(d);
d.modify(aobj, [&op](account_role_object &obj) {
if (op.name)
obj.name = *op.name;
if (op.metadata)
obj.metadata = *op.metadata;
obj.allowed_operations.insert(op.allowed_operations_to_add.begin(), op.allowed_operations_to_add.end());
obj.whitelisted_accounts.insert(op.accounts_to_add.begin(), op.accounts_to_add.end());
for (const auto &op_type : op.allowed_operations_to_remove)
obj.allowed_operations.erase(op_type);
for (const auto &acc : op.accounts_to_remove)
obj.whitelisted_accounts.erase(acc);
if (op.valid_to)
obj.valid_to = *op.valid_to;
});
return void_result();
}
FC_CAPTURE_AND_RETHROW((op))
}
void_result account_role_delete_evaluator::do_evaluate(const account_role_delete_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.owner(d);
const account_role_object &aobj = op.account_role_id(d);
FC_ASSERT(aobj.owner == op.owner, "Only owner account can delete account role object");
return void_result();
}
FC_CAPTURE_AND_RETHROW((op))
}
void_result account_role_delete_evaluator::do_apply(const account_role_delete_operation &op)
{
try
{
database &d = db();
const account_role_object &aobj = op.account_role_id(d);
d.remove(aobj);
return void_result();
}
FC_CAPTURE_AND_RETHROW((op))
}
} // namespace chain
} // namespace graphene

View file

@ -42,6 +42,8 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o
database& d = db();
FC_ASSERT(d.is_asset_creation_allowed(op.symbol), "Asset creation not allowed at current time");
const auto& chain_parameters = d.get_global_properties().parameters;
FC_ASSERT( op.common_options.whitelist_authorities.size() <= chain_parameters.maximum_asset_whitelist_authorities );
FC_ASSERT( op.common_options.blacklist_authorities.size() <= chain_parameters.maximum_asset_whitelist_authorities );
@ -76,7 +78,7 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o
{
auto dotpos = op.symbol.rfind( '.' );
if( dotpos != std::string::npos )
{
auto prefix = op.symbol.substr( 0, dotpos );
auto asset_symbol_itr = asset_indx.find( prefix );
@ -119,7 +121,7 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o
FC_ASSERT( op.bitasset_opts );
FC_ASSERT( op.precision == op.bitasset_opts->short_backing_asset(d).precision );
}
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -174,7 +176,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o
a.options.core_exchange_rate.base.asset_id = next_asset_id;
a.dynamic_asset_data_id = dyn_asset.id;
if( op.bitasset_opts.valid() )
a.bitasset_data_id = bit_asset_id;
});
@ -188,6 +190,8 @@ void_result lottery_asset_create_evaluator::do_evaluate( const lottery_asset_cre
database& d = db();
FC_ASSERT(d.is_asset_creation_allowed(op.symbol), "Lottery asset creation not allowed at current time");
const auto& chain_parameters = d.get_global_properties().parameters;
FC_ASSERT( op.common_options.whitelist_authorities.size() <= chain_parameters.maximum_asset_whitelist_authorities );
FC_ASSERT( op.common_options.blacklist_authorities.size() <= chain_parameters.maximum_asset_whitelist_authorities );
@ -222,7 +226,7 @@ void_result lottery_asset_create_evaluator::do_evaluate( const lottery_asset_cre
{
auto dotpos = op.symbol.rfind( '.' );
if( dotpos != std::string::npos )
{
auto prefix = op.symbol.substr( 0, dotpos );
auto asset_symbol_itr = asset_indx.find( prefix );
@ -575,7 +579,7 @@ void_result asset_update_dividend_evaluator::do_evaluate(const asset_update_divi
auto& params = db().get_global_properties().parameters;
if (o.new_options.payout_interval &&
*o.new_options.payout_interval < params.maintenance_interval)
FC_THROW("New payout interval may not be less than the maintenance interval",
FC_THROW("New payout interval may not be less than the maintenance interval",
("new_payout_interval", o.new_options.payout_interval)("maintenance_interval", params.maintenance_interval));
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }

View file

@ -4,37 +4,13 @@
#include <graphene/chain/custom_account_authority_object.hpp>
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/hardfork.hpp>
#include <graphene/chain/rbac_hardfork_visitor.hpp>
namespace graphene
{
namespace chain
{
struct rbac_operation_hardfork_visitor
{
typedef void result_type;
const fc::time_point_sec block_time;
rbac_operation_hardfork_visitor(const fc::time_point_sec bt) : block_time(bt) {}
void operator()(int op_type) const
{
int first_allowed_op = operation::tag<custom_permission_create_operation>::value;
switch (op_type)
{
case operation::tag<custom_permission_create_operation>::value:
case operation::tag<custom_permission_update_operation>::value:
case operation::tag<custom_permission_delete_operation>::value:
case operation::tag<custom_account_authority_create_operation>::value:
case operation::tag<custom_account_authority_update_operation>::value:
case operation::tag<custom_account_authority_delete_operation>::value:
FC_ASSERT(block_time >= HARDFORK_NFT_TIME, "Custom permission not allowed on this operation yet!");
break;
default:
FC_ASSERT(op_type < first_allowed_op, "Custom permission not allowed on this operation!");
}
}
};
void_result create_custom_account_authority_evaluator::do_evaluate(const custom_account_authority_create_operation &op)
{
try
@ -149,4 +125,5 @@ void_result delete_custom_account_authority_evaluator::do_apply(const custom_acc
}
} // namespace chain
} // namespace graphene
} // namespace graphene

View file

@ -44,11 +44,11 @@
#include <fc/crypto/digest.hpp>
namespace {
struct proposed_operations_digest_accumulator
{
typedef void result_type;
void operator()(const graphene::chain::proposal_create_operation& proposal)
{
for (auto& operation: proposal.proposed_ops)
@ -56,20 +56,20 @@ namespace {
proposed_operations_digests.push_back(fc::digest(operation.op));
}
}
//empty template method is needed for all other operation types
//we can ignore them, we are interested in only proposal_create_operation
template<class T>
void operator()(const T&)
void operator()(const T&)
{}
std::vector<fc::sha256> proposed_operations_digests;
};
std::vector<fc::sha256> gather_proposed_operations_digests(const graphene::chain::transaction& trx)
{
proposed_operations_digest_accumulator digest_accumulator;
for (auto& operation: trx.operations)
{
if( operation.which() != graphene::chain::operation::tag<graphene::chain::betting_market_group_create_operation>::value
@ -78,7 +78,7 @@ namespace {
else
edump( ("Found dup"));
}
return digest_accumulator.proposed_operations_digests;
}
}
@ -148,24 +148,24 @@ std::vector<block_id_type> database::get_block_ids_on_fork(block_id_type head_of
result.emplace_back(branches.first.back()->previous_id());
return result;
}
void database::check_tansaction_for_duplicated_operations(const signed_transaction& trx)
void database::check_transaction_for_duplicated_operations(const signed_transaction& trx)
{
const auto& proposal_index = get_index<proposal_object>();
std::set<fc::sha256> existed_operations_digests;
proposal_index.inspect_all_objects( [&](const object& obj){
const proposal_object& proposal = static_cast<const proposal_object&>(obj);
auto proposed_operations_digests = gather_proposed_operations_digests( proposal.proposed_transaction );
existed_operations_digests.insert( proposed_operations_digests.begin(), proposed_operations_digests.end() );
});
for (auto& pending_transaction: _pending_tx)
{
auto proposed_operations_digests = gather_proposed_operations_digests(pending_transaction);
existed_operations_digests.insert(proposed_operations_digests.begin(), proposed_operations_digests.end());
}
auto proposed_operations_digests = gather_proposed_operations_digests(trx);
for (auto& digest: proposed_operations_digests)
{
@ -337,7 +337,7 @@ void database::verify_signing_witness( const signed_block& new_block, const fork
FC_ASSERT( new_block.witness == wid, "Witness produced block at wrong time",
("block witness",new_block.witness)("scheduled",wid)("slot_num",slot_num) );
FC_ASSERT( new_block.validate_signee( wid(*this).signing_key ) );
}
}
}
void database::update_witnesses( fork_item& fork_entry )const
@ -351,7 +351,7 @@ void database::update_witnesses( fork_item& fork_entry )const
const witness_schedule_object& wso = get_witness_schedule_object();
fork_entry.scheduled_witnesses = std::make_shared< vector< pair< witness_id_type, public_key_type > > >();
fork_entry.scheduled_witnesses->reserve( wso.current_shuffled_witnesses.size() );
for( size_t i = 0; i < wso.current_shuffled_witnesses.size(); ++i )
{
const auto& witness = wso.current_shuffled_witnesses[i](*this);
@ -425,6 +425,7 @@ processed_transaction database::push_proposal(const proposal_object& proposal)
auto session = _undo_db.start_undo_session(true);
for( auto& op : proposal.proposed_transaction.operations )
eval_state.operation_results.emplace_back(apply_operation(eval_state, op));
remove_son_proposal(proposal);
remove(proposal);
session.merge();
} catch ( const fc::exception& e ) {
@ -550,7 +551,7 @@ signed_block database::_generate_block(
pending_block.timestamp = when;
pending_block.transaction_merkle_root = pending_block.calculate_merkle_root();
pending_block.witness = witness_id;
// Genesis witnesses start with a default initial secret
if( witness_obj.next_secret_hash == secret_hash_type::hash( secret_hash_type() ) ) {
pending_block.previous_secret = secret_hash_type();
@ -560,7 +561,7 @@ signed_block database::_generate_block(
fc::raw::pack( last_enc, witness_obj.previous_secret );
pending_block.previous_secret = last_enc.result();
}
secret_hash_type::encoder next_enc;
fc::raw::pack( next_enc, block_signing_private_key );
fc::raw::pack( next_enc, pending_block.previous_secret );
@ -691,14 +692,19 @@ void database::_apply_block( const signed_block& next_block )
// For VOPs derived directly from a real op,
// use the real op's (block_num,trx_in_block,op_in_trx), virtual_op starts from 1.
// For VOPs created after processed all transactions,
// trx_in_block = the_block.trsanctions.size(), virtual_op starts from 0.
// trx_in_block = the_block.trsanctions.size(), virtual_op starts from 0.
++_current_trx_in_block;
_current_op_in_trx = 0;
_current_virtual_op = 0;
_current_virtual_op = 0;
}
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM) {
update_witness_schedule(next_block);
if(global_props.active_sons.size() > 0) {
update_son_schedule(next_block);
}
}
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM)
update_witness_schedule(next_block);
const uint32_t missed = update_witness_missed_blocks( next_block );
update_global_dynamic_data( next_block, missed );
update_signing_witness(signing_witness, next_block);
@ -707,9 +713,9 @@ void database::_apply_block( const signed_block& next_block )
// Are we at the maintenance interval?
if( maint_needed )
perform_chain_maintenance(next_block, global_props);
check_ending_lotteries();
create_block_summary(next_block);
place_delayed_bets(); // must happen after update_global_dynamic_data() updates the time
clear_expired_transactions();
@ -728,8 +734,13 @@ void database::_apply_block( const signed_block& next_block )
// update_global_dynamic_data() as perhaps these methods only need
// to be called for header validation?
update_maintenance_flag( maint_needed );
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
update_witness_schedule();
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM) {
update_witness_schedule();
if(global_props.active_sons.size() > 0) {
update_son_schedule();
}
}
if( !_node_property_object.debug_updates.empty() )
apply_debug_updates();
@ -775,7 +786,7 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
auto& trx_idx = get_mutable_index_type<transaction_index>();
const chain_id_type& chain_id = get_chain_id();
transaction_id_type trx_id;
if( !(skip & skip_transaction_dupe_check) )
{
trx_id = trx.id();
@ -788,12 +799,14 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
if( !(skip & (skip_transaction_signatures | skip_authority_check) ) )
{
auto get_active = [&]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [&]( account_id_type id ) { return &id(*this).owner; };
auto get_custom = [&]( account_id_type id, const operation& op ) {
auto get_active = [this]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [this]( account_id_type id ) { return &id(*this).owner; };
auto get_custom = [this]( account_id_type id, const operation& op ) {
return get_account_custom_authorities(id, op);
};
trx.verify_authority( chain_id, get_active, get_owner, get_custom, get_global_properties().parameters.max_authority_depth );
trx.verify_authority( chain_id, get_active, get_owner, get_custom,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(head_block_time()),
get_global_properties().parameters.max_authority_depth );
}
//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
@ -871,7 +884,7 @@ const witness_object& database::validate_block_header( uint32_t skip, const sign
FC_ASSERT( secret_hash_type::hash( next_block.previous_secret ) == witness.next_secret_hash, "",
( "previous_secret", next_block.previous_secret )( "next_secret_hash", witness.next_secret_hash ) );
if( !(skip&skip_witness_signature) )
if( !(skip&skip_witness_signature) )
FC_ASSERT( next_block.validate_signee( witness.signing_key ) );
if( !(skip&skip_witness_schedule_check) )

View file

@ -30,6 +30,9 @@
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/custom_account_authority_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/chain/son_object.hpp>
#include <graphene/chain/son_proposal_object.hpp>
#include <ctime>
#include <algorithm>
@ -192,4 +195,148 @@ bool database::item_locked(const nft_id_type &item) const
auto items_itr = market_items._locked_items.find(item);
return (items_itr != market_items._locked_items.end());
}
bool database::account_role_valid(const account_role_object &aro, account_id_type account, optional<int> op_type) const
{
return (aro.valid_to > head_block_time()) &&
(aro.whitelisted_accounts.find(account) != aro.whitelisted_accounts.end()) &&
(!op_type || (aro.allowed_operations.find(*op_type) != aro.allowed_operations.end()));
}
std::set<son_id_type> database::get_sons_being_deregistered()
{
std::set<son_id_type> ret;
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get< by_id >();
for( auto& son_proposal : son_proposal_idx )
{
if(son_proposal.proposal_type == son_proposal_type::son_deregister_proposal)
{
ret.insert(son_proposal.son_id);
}
}
return ret;
}
std::set<son_id_type> database::get_sons_to_be_deregistered()
{
std::set<son_id_type> ret;
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
for( auto& son : son_idx )
{
if(son.status == son_status::in_maintenance)
{
auto& stats = son.statistics(*this);
// TODO : We need to add a function that returns if we can deregister SON
// i.e. with introduction of PW code, we have to make a decision if the SON
// is needed for release of funds from the PW
if(head_block_time() - stats.last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time()))
{
ret.insert(son.id);
}
}
}
return ret;
}
std::set<son_id_type> database::get_sons_being_reported_down()
{
std::set<son_id_type> ret;
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get< by_id >();
for( auto& son_proposal : son_proposal_idx )
{
if(son_proposal.proposal_type == son_proposal_type::son_report_down_proposal)
{
ret.insert(son_proposal.son_id);
}
}
return ret;
}
fc::optional<operation> database::create_son_deregister_proposal( son_id_type son_id, account_id_type paying_son )
{
son_deregister_operation son_dereg_op;
son_dereg_op.payer = get_global_properties().parameters.son_account();
son_dereg_op.son_id = son_id;
proposal_create_operation proposal_op;
proposal_op.fee_paying_account = paying_son;
proposal_op.proposed_ops.push_back( op_wrapper( son_dereg_op ) );
uint32_t lifetime = ( get_global_properties().parameters.block_interval * get_global_properties().active_witnesses.size() ) * 3;
proposal_op.expiration_time = time_point_sec( head_block_time().sec_since_epoch() + lifetime );
return proposal_op;
}
signed_transaction database::create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op )
{
signed_transaction processed_trx;
auto dyn_props = get_dynamic_global_properties();
processed_trx.set_reference_block( dyn_props.head_block_id );
processed_trx.set_expiration( head_block_time() + get_global_properties().parameters.maximum_time_until_expiration );
processed_trx.operations.push_back( op );
current_fee_schedule().set_fee( processed_trx.operations.back() );
processed_trx.sign( signing_private_key, get_chain_id() );
return processed_trx;
}
bool database::is_son_dereg_valid( son_id_type son_id )
{
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
auto son = son_idx.find( son_id );
if(son == son_idx.end())
{
return false;
}
return (son->status == son_status::in_maintenance &&
(head_block_time() - son->statistics(*this).last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time())));
}
bool database::is_son_active( son_id_type son_id )
{
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
auto son = son_idx.find( son_id );
if(son == son_idx.end())
{
return false;
}
const global_property_object& gpo = get_global_properties();
vector<son_id_type> active_son_ids;
active_son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(active_son_ids, active_son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
auto it_son = std::find(active_son_ids.begin(), active_son_ids.end(), son_id);
return (it_son != active_son_ids.end());
}
bool database::is_asset_creation_allowed(const string &symbol)
{
time_point_sec now = head_block_time();
std::unordered_set<std::string> post_son_hf_symbols = {"ETH", "USDT", "BNB", "ADA", "DOGE", "XRP", "USDC", "DOT", "UNI", "BUSD", "BCH", "LTC", "SOL", "LINK", "MATIC", "THETA",
"WBTC", "XLM", "ICP", "DAI", "VET", "ETC", "TRX", "FIL", "XMR", "EGR", "EOS", "SHIB", "AAVE", "CRO", "ALGO", "AMP", "BTCB",
"BSV", "KLAY", "CAKE", "FTT", "LEO", "XTZ", "TFUEL", "MIOTA", "LUNA", "NEO", "ATOM", "MKR", "FEI", "WBNB", "UST", "AVAX",
"STEEM", "HIVE", "HBD", "SBD", "BTS"};
if (symbol == "BTC")
{
if (now < HARDFORK_SON_TIME)
return false;
}
if (post_son_hf_symbols.find(symbol) != post_son_hf_symbols.end())
{
if (now >= HARDFORK_SON_TIME)
return false;
}
return true;
}
} }

View file

@ -52,6 +52,7 @@
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/custom_account_authority_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/chain/nft_object.hpp>
@ -60,6 +61,13 @@
#include <graphene/chain/event_object.hpp>
#include <graphene/chain/betting_market_object.hpp>
#include <graphene/chain/global_betting_statistics_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/sidechain_address_object.hpp>
#include <graphene/chain/sidechain_transaction_object.hpp>
#include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/asset_evaluator.hpp>
@ -86,6 +94,16 @@
#include <graphene/chain/offer_evaluator.hpp>
#include <graphene/chain/nft_evaluator.hpp>
#include <graphene/chain/account_role_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/protocol/fee_schedule.hpp>
#include <fc/uint128.hpp>
#include <fc/crypto/digest.hpp>
@ -183,6 +201,9 @@ const uint8_t offer_object::type_id;
const uint8_t offer_history_object::space_id;
const uint8_t offer_history_object::type_id;
const uint8_t account_role_object::space_id;
const uint8_t account_role_object::type_id;
void database::initialize_evaluators()
{
_operation_evaluators.resize(255);
@ -272,6 +293,28 @@ void database::initialize_evaluators()
register_evaluator<nft_safe_transfer_from_evaluator>();
register_evaluator<nft_approve_evaluator>();
register_evaluator<nft_set_approval_for_all_evaluator>();
register_evaluator<account_role_create_evaluator>();
register_evaluator<account_role_update_evaluator>();
register_evaluator<account_role_delete_evaluator>();
register_evaluator<create_son_evaluator>();
register_evaluator<update_son_evaluator>();
register_evaluator<deregister_son_evaluator>();
register_evaluator<son_heartbeat_evaluator>();
register_evaluator<son_report_down_evaluator>();
register_evaluator<son_maintenance_evaluator>();
register_evaluator<recreate_son_wallet_evaluator>();
register_evaluator<update_son_wallet_evaluator>();
register_evaluator<create_son_wallet_deposit_evaluator>();
register_evaluator<process_son_wallet_deposit_evaluator>();
register_evaluator<create_son_wallet_withdraw_evaluator>();
register_evaluator<process_son_wallet_withdraw_evaluator>();
register_evaluator<add_sidechain_address_evaluator>();
register_evaluator<update_sidechain_address_evaluator>();
register_evaluator<delete_sidechain_address_evaluator>();
register_evaluator<sidechain_transaction_create_evaluator>();
register_evaluator<sidechain_transaction_sign_evaluator>();
register_evaluator<sidechain_transaction_send_evaluator>();
register_evaluator<sidechain_transaction_settle_evaluator>();
}
void database::initialize_indexes()
@ -288,6 +331,7 @@ void database::initialize_indexes()
acnt_index->add_secondary_index<account_referrer_index>();
add_index< primary_index<committee_member_index, 8> >(); // 256 members per chunk
add_index< primary_index<son_index> >();
add_index< primary_index<witness_index, 10> >(); // 1024 witnesses per chunk
add_index< primary_index<limit_order_index > >();
add_index< primary_index<call_order_index > >();
@ -320,6 +364,15 @@ void database::initialize_indexes()
add_index< primary_index<nft_metadata_index > >();
add_index< primary_index<nft_index > >();
add_index< primary_index<account_role_index> >();
add_index< primary_index<son_proposal_index> >();
add_index< primary_index<son_wallet_index> >();
add_index< primary_index<son_wallet_deposit_index> >();
add_index< primary_index<son_wallet_withdraw_index> >();
add_index< primary_index<sidechain_address_index> >();
add_index< primary_index<sidechain_transaction_index> >();
//Implementation object indexes
add_index< primary_index<transaction_index > >();
@ -336,6 +389,7 @@ void database::initialize_indexes()
add_index< primary_index<flat_index< block_summary_object >> >();
add_index< primary_index<simple_index<chain_property_object > > >();
add_index< primary_index<simple_index<witness_schedule_object > > >();
add_index< primary_index<simple_index<son_schedule_object > > >();
add_index< primary_index<simple_index<budget_record_object > > >();
add_index< primary_index< special_authority_index > >();
add_index< primary_index< buyback_index > >();
@ -350,6 +404,7 @@ 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<son_stats_index > >();
}
@ -994,6 +1049,29 @@ void database::init_genesis(const genesis_state_type& genesis_state)
});
FC_ASSERT( _p_witness_schedule_obj->id == witness_schedule_id_type() );
// Initialize witness schedule
#ifndef NDEBUG
const son_schedule_object& sso =
#endif
create<son_schedule_object>([&](son_schedule_object& _sso)
{
// for scheduled
memset(_sso.rng_seed.begin(), 0, _sso.rng_seed.size());
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
auto init_witnesses = get_global_properties().active_witnesses;
_sso.scheduler = son_scheduler();
_sso.scheduler._min_token_count = std::max(int(init_witnesses.size()) / 2, 1);
_sso.last_scheduling_block = 0;
_sso.recent_slots_filled = std::numeric_limits<fc::uint128_t>::max();
});
assert( sso.id == son_schedule_id_type() );
// Enable fees
modify(get_global_properties(), [&genesis_state](global_property_object& p) {
p.parameters.current_fees = genesis_state.initial_parameters.current_fees;

View file

@ -22,6 +22,10 @@
* THE SOFTWARE.
*/
#include <boost/multiprecision/integer.hpp>
#include <fc/uint128.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/fba_accumulator_id.hpp>
#include <graphene/chain/hardfork.hpp>
@ -37,6 +41,7 @@
#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/vesting_balance_object.hpp>
#include <graphene/chain/vote_count.hpp>
#include <graphene/chain/witness_object.hpp>
@ -78,6 +83,32 @@ vector<std::reference_wrapper<const typename Index::object_type>> database::sort
return refs;
}
template<>
vector<std::reference_wrapper<const son_object>> database::sort_votable_objects<son_index>(size_t count) const
{
const auto& all_sons = get_index_type<son_index>().indices().get< by_id >();
std::vector<std::reference_wrapper<const son_object>> refs;
for( auto& son : all_sons )
{
if(son.has_valid_config() && son.status != son_status::deregistered)
{
refs.push_back(std::cref(son));
}
}
count = std::min(count, refs.size());
std::partial_sort(refs.begin(), refs.begin() + count, refs.end(),
[this](const son_object& a, const son_object& b)->bool {
share_type oa_vote = _vote_tally_buffer[a.vote_id];
share_type ob_vote = _vote_tally_buffer[b.vote_id];
if( oa_vote != ob_vote )
return oa_vote > ob_vote;
return a.vote_id < b.vote_id;
});
refs.resize(count, refs.front());
return refs;
}
template<class Type>
void database::perform_account_maintenance(Type tally_helper)
{
@ -151,6 +182,231 @@ void database::update_worker_votes()
}
}
void database::pay_sons()
{
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, &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, &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){
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);
});
//Remove the amount paid out to SON from global SON Budget
modify( dpo, [&]( dynamic_global_property_object& _dpo )
{
_dpo.son_budget -= pay;
} );
//Reset the tx counter in each son statistics object
modify( s, [&]( son_statistics_object& _s)
{
_s.total_txs_signed += _s.txs_signed;
_s.txs_signed = 0;
});
}
});
//Note the last son pay out time
modify( dpo, [&]( dynamic_global_property_object& _dpo )
{
_dpo.last_son_payout_time = now;
});
}
}
void database::update_son_metrics(const vector<son_info>& curr_active_sons)
{
vector<son_id_type> current_sons;
current_sons.reserve(curr_active_sons.size());
std::transform(curr_active_sons.begin(), curr_active_sons.end(),
std::inserter(current_sons, current_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
for( auto& son : son_idx )
{
auto& stats = son.statistics(*this);
bool is_active_son = (std::find(current_sons.begin(), current_sons.end(), son.id) != current_sons.end());
modify( stats, [&]( son_statistics_object& _stats )
{
_stats.total_downtime += _stats.current_interval_downtime;
_stats.current_interval_downtime = 0;
if(is_active_son)
{
_stats.total_voted_time = _stats.total_voted_time + get_global_properties().parameters.maintenance_interval;
}
});
}
}
void database::update_son_statuses(const vector<son_info>& curr_active_sons, const vector<son_info>& new_active_sons)
{
vector<son_id_type> current_sons, new_sons;
vector<son_id_type> sons_to_remove, sons_to_add;
const auto& idx = get_index_type<son_index>().indices().get<by_id>();
current_sons.reserve(curr_active_sons.size());
std::transform(curr_active_sons.begin(), curr_active_sons.end(),
std::inserter(current_sons, current_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
new_sons.reserve(new_active_sons.size());
std::transform(new_active_sons.begin(), new_active_sons.end(),
std::inserter(new_sons, new_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
// find all cur_active_sons members that is not in new_active_sons
for_each(current_sons.begin(), current_sons.end(),
[&sons_to_remove, &new_sons](const son_id_type& si)
{
if(std::find(new_sons.begin(), new_sons.end(), si) ==
new_sons.end())
{
sons_to_remove.push_back(si);
}
}
);
for( const auto& sid : sons_to_remove )
{
auto son = idx.find( sid );
if(son == idx.end()) // SON is deleted already
continue;
// keep maintenance status for nodes becoming inactive
if(son->status == son_status::active)
{
modify( *son, [&]( son_object& obj ){
obj.status = son_status::inactive;
});
}
}
// find all new_active_sons members that is not in cur_active_sons
for_each(new_sons.begin(), new_sons.end(),
[&sons_to_add, &current_sons](const son_id_type& si)
{
if(std::find(current_sons.begin(), current_sons.end(), si) ==
current_sons.end())
{
sons_to_add.push_back(si);
}
}
);
for( const auto& sid : sons_to_add )
{
auto son = idx.find( sid );
FC_ASSERT(son != idx.end(), "Invalid SON in active list, id={sonid}.", ("sonid", sid));
// keep maintenance status for new nodes
if(son->status == son_status::inactive)
{
modify( *son, [&]( son_object& obj ){
obj.status = son_status::active;
});
}
}
ilog("New SONS");
for(size_t i = 0; i < new_sons.size(); i++) {
auto son = idx.find( new_sons[i] );
if(son == idx.end()) // SON is deleted already
continue;
ilog( "${s}, status = ${ss}, total_votes = ${sv}", ("s", new_sons[i])("ss", son->status)("sv", son->total_votes) );
}
if( sons_to_remove.size() > 0 )
{
remove_inactive_son_proposals(sons_to_remove);
}
}
void database::update_son_wallet(const vector<son_info>& new_active_sons)
{
bool should_recreate_pw = true;
// Expire for current son_wallet_object wallet, if exists
const auto& idx_swi = get_index_type<son_wallet_index>().indices().get<by_id>();
auto obj = idx_swi.rbegin();
if (obj != idx_swi.rend()) {
// Compare current wallet SONs and to-be lists of active sons
auto cur_wallet_sons = (*obj).sons;
bool wallet_son_sets_equal = (cur_wallet_sons.size() == new_active_sons.size());
if (wallet_son_sets_equal) {
for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) {
wallet_son_sets_equal = wallet_son_sets_equal && cur_wallet_sons.at(i) == new_active_sons.at(i);
}
}
should_recreate_pw = !wallet_son_sets_equal;
if (should_recreate_pw) {
modify(*obj, [&, obj](son_wallet_object &swo) {
swo.expires = head_block_time();
});
}
}
should_recreate_pw = should_recreate_pw && (new_active_sons.size() >= get_chain_properties().immutable_parameters.min_son_count);
if (should_recreate_pw) {
// Create new son_wallet_object, to initiate wallet recreation
create<son_wallet_object>( [&]( son_wallet_object& obj ) {
obj.valid_from = head_block_time();
obj.expires = time_point_sec::maximum();
obj.sons.insert(obj.sons.end(), new_active_sons.begin(), new_active_sons.end());
});
}
}
void database::pay_workers( share_type& budget )
{
const auto head_time = head_block_time();
@ -208,7 +464,7 @@ void database::update_active_witnesses()
/// accounts that vote for 0 or 1 witness do not get to express an opinion on
/// the number of witnesses to have (they abstain and are non-voting accounts)
share_type stake_tally = 0;
share_type stake_tally = 0;
size_t witness_count = 0;
if( stake_target > 0 )
@ -307,7 +563,7 @@ void database::update_active_witnesses()
void database::update_active_committee_members()
{ try {
assert( _committee_count_histogram_buffer.size() > 0 );
share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2;
share_type stake_target = (_total_voting_stake-_committee_count_histogram_buffer[0]) / 2;
/// accounts that vote for 0 or 1 witness do not get to express an opinion on
/// the number of witnesses to have (they abstain and are non-voting accounts)
@ -396,6 +652,146 @@ void database::update_active_committee_members()
});
} FC_CAPTURE_AND_RETHROW() }
void database::update_active_sons()
{ try {
assert( _son_count_histogram_buffer.size() > 0 );
share_type stake_target = (_total_voting_stake-_son_count_histogram_buffer[0]) / 2;
/// accounts that vote for 0 or 1 son do not get to express an opinion on
/// the number of sons to have (they abstain and are non-voting accounts)
share_type stake_tally = 0;
size_t son_count = 0;
if( stake_target > 0 )
{
while( (son_count < _son_count_histogram_buffer.size() - 1)
&& (stake_tally <= stake_target) )
{
stake_tally += _son_count_histogram_buffer[++son_count];
}
}
const global_property_object& gpo = get_global_properties();
const chain_parameters& cp = gpo.parameters;
auto sons = sort_votable_objects<son_index>(cp.maximum_son_count());
const auto& all_sons = get_index_type<son_index>().indices();
auto& local_vote_buffer_ref = _vote_tally_buffer;
for( const son_object& son : all_sons )
{
if(son.status == son_status::request_maintenance)
{
auto& stats = son.statistics(*this);
modify( stats, [&]( son_statistics_object& _s){
_s.last_down_timestamp = head_block_time();
});
}
modify( son, [local_vote_buffer_ref]( son_object& obj ){
obj.total_votes = local_vote_buffer_ref[obj.vote_id];
if(obj.status == son_status::request_maintenance)
obj.status = son_status::in_maintenance;
});
}
// Update SON authority
if( gpo.parameters.son_account() != GRAPHENE_NULL_ACCOUNT )
{
modify( get(gpo.parameters.son_account()), [&]( account_object& a )
{
if( head_block_time() < HARDFORK_533_TIME )
{
map<account_id_type, uint64_t> weights;
a.active.weight_threshold = 0;
a.active.account_auths.clear();
for( const son_object& son : sons )
{
weights.emplace(son.son_account, uint64_t(1));
}
for( const auto& weight : weights )
{
// Ensure that everyone has at least one vote. Zero weights aren't allowed.
a.active.account_auths[weight.first] += 1;
a.active.weight_threshold += 1;
}
a.active.weight_threshold *= 2;
a.active.weight_threshold /= 3;
a.active.weight_threshold += 1;
}
else
{
vote_counter vc;
for( const son_object& son : sons )
vc.add( son.son_account, UINT64_C(1) );
vc.finish_2_3( a.active );
}
} );
}
// Compare current and to-be lists of active sons
auto cur_active_sons = gpo.active_sons;
vector<son_info> new_active_sons;
const auto &acc = get(gpo.parameters.son_account());
for( const son_object& son : sons ) {
son_info swi;
swi.son_id = son.id;
swi.weight = acc.active.account_auths.at(son.son_account);
swi.signing_key = son.signing_key;
swi.sidechain_public_keys = son.sidechain_public_keys;
new_active_sons.push_back(swi);
}
bool son_sets_equal = (cur_active_sons.size() == new_active_sons.size());
if (son_sets_equal) {
for( size_t i = 0; i < cur_active_sons.size(); i++ ) {
son_sets_equal = son_sets_equal && cur_active_sons.at(i) == new_active_sons.at(i);
}
}
if (son_sets_equal) {
ilog( "Active SONs set NOT CHANGED" );
} else {
ilog( "Active SONs set CHANGED" );
update_son_wallet(new_active_sons);
update_son_statuses(cur_active_sons, new_active_sons);
}
// Update son performance metrics
update_son_metrics(cur_active_sons);
modify(gpo, [&]( global_property_object& gp ){
gp.active_sons.clear();
gp.active_sons.reserve(new_active_sons.size());
gp.active_sons.insert(gp.active_sons.end(), new_active_sons.begin(), new_active_sons.end());
});
const son_schedule_object& sso = son_schedule_id_type()(*this);
modify(sso, [&](son_schedule_object& _sso)
{
flat_set<son_id_type> active_sons;
active_sons.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(active_sons, active_sons.end()),
[](const son_info& swi) {
return swi.son_id;
});
_sso.scheduler.update(active_sons);
// similar to witness, produce schedule for sons
if(cur_active_sons.size() == 0 && new_active_sons.size() > 0)
{
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
for( size_t i=0; i<new_active_sons.size(); ++i )
_sso.scheduler.produce_schedule(rng);
}
});
} FC_CAPTURE_AND_RETHROW() }
void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const
{
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
@ -484,6 +880,17 @@ void database::process_budget()
rec.witness_budget = witness_budget;
available_funds -= witness_budget;
// We should not factor-in the son budget before SON HARDFORK
share_type son_budget = 0;
if(now >= HARDFORK_SON_TIME){
rec.leftover_son_funds = dpo.son_budget;
available_funds += rec.leftover_son_funds;
son_budget = gpo.parameters.son_pay_max();
son_budget = std::min(son_budget, available_funds);
rec.son_budget = son_budget;
available_funds -= son_budget;
}
fc::uint128_t worker_budget_u128 = gpo.parameters.worker_budget_per_day.value;
worker_budget_u128 *= uint64_t(time_to_maint);
worker_budget_u128 /= 60*60*24;
@ -503,9 +910,11 @@ void database::process_budget()
rec.supply_delta = rec.witness_budget
+ rec.worker_budget
+ rec.son_budget
- rec.leftover_worker_funds
- rec.from_accumulated_fees
- rec.from_unused_witness_budget;
- rec.from_unused_witness_budget
- rec.leftover_son_funds;
modify(core, [&]( asset_dynamic_data_object& _core )
{
@ -514,9 +923,11 @@ void database::process_budget()
assert( rec.supply_delta ==
witness_budget
+ worker_budget
+ son_budget
- leftover_worker_funds
- _core.accumulated_fees
- dpo.witness_budget
- dpo.son_budget
);
_core.accumulated_fees = 0;
});
@ -527,6 +938,7 @@ void database::process_budget()
// available_funds, we replace it with witness_budget
// instead of adding it.
_dpo.witness_budget = witness_budget;
_dpo.son_budget = son_budget;
_dpo.last_budget_time = now;
});
@ -942,14 +1354,23 @@ void clear_expired_custom_account_authorities(database& db)
}
}
void clear_expired_account_roles(database& db)
{
const auto& arindex = db.get_index_type<account_role_index>().indices().get<by_expiration>();
while(!arindex.empty() && arindex.begin()->valid_to < db.head_block_time())
{
db.remove(*arindex.begin());
}
}
// Schedules payouts from a dividend distribution account to the current holders of the
// dividend-paying asset. This takes any deposits made to the dividend distribution account
// since the last time it was called, and distributes them to the current owners of the
// dividend-paying asset according to the amount they own.
void schedule_pending_dividend_balances(database& db,
void schedule_pending_dividend_balances(database& db,
const asset_object& dividend_holder_asset_obj,
const asset_dividend_data_object& dividend_data,
const fc::time_point_sec& current_head_block_time,
const fc::time_point_sec& current_head_block_time,
const account_balance_index& balance_index,
const vesting_balance_index& vesting_index,
const total_distributed_dividend_balance_object_index& distributed_dividend_balance_index,
@ -958,7 +1379,7 @@ void schedule_pending_dividend_balances(database& db,
dlog("Processing dividend payments for dividend holder asset type ${holder_asset} at time ${t}",
("holder_asset", dividend_holder_asset_obj.symbol)("t", db.head_block_time()));
auto balance_by_acc_index = db.get_index_type< primary_index< account_balance_index > >().get_secondary_index< balances_by_account_index >();
auto current_distribution_account_balance_range =
auto current_distribution_account_balance_range =
//balance_index.indices().get<by_account_asset>().equal_range(boost::make_tuple(dividend_data.dividend_distribution_account));
balance_by_acc_index.get_account_balances(dividend_data.dividend_distribution_account);
auto previous_distribution_account_balance_range =
@ -969,7 +1390,7 @@ void schedule_pending_dividend_balances(database& db,
const auto& gpo = db.get_global_properties();
// get the list of accounts that hold nonzero balances of the dividend asset
auto holder_balances_begin =
auto holder_balances_begin =
balance_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(dividend_holder_asset_obj.id));
auto holder_balances_end =
balance_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(dividend_holder_asset_obj.id, share_type()));
@ -1029,7 +1450,7 @@ void schedule_pending_dividend_balances(database& db,
("previous", (int64_t)std::distance(previous_distribution_account_balance_range.first, previous_distribution_account_balance_range.second)));
// when we pay out the dividends to the holders, we need to know the total balance of the dividend asset in all
// accounts other than the distribution account (it would be silly to distribute dividends back to
// accounts other than the distribution account (it would be silly to distribute dividends back to
// the distribution account)
share_type total_balance_of_dividend_asset;
if(db.head_block_time() >= HARDFORK_GPOS_TIME && dividend_holder_asset_obj.symbol == GRAPHENE_SYMBOL) { // only core
@ -1060,7 +1481,7 @@ void schedule_pending_dividend_balances(database& db,
share_type previous_balance;
asset_id_type payout_asset_type;
if (previous_distribution_account_balance_iter == previous_distribution_account_balance_range.second ||
if (previous_distribution_account_balance_iter == previous_distribution_account_balance_range.second ||
current_distribution_account_balance_iter->second->asset_type < previous_distribution_account_balance_iter->dividend_payout_asset_type)
{
// there are no more previous balances or there is no previous balance for this particular asset type
@ -1068,7 +1489,7 @@ void schedule_pending_dividend_balances(database& db,
current_balance = current_distribution_account_balance_iter->second->balance;
idump((payout_asset_type)(current_balance));
}
else if (current_distribution_account_balance_iter == current_distribution_account_balance_range.end() ||
else if (current_distribution_account_balance_iter == current_distribution_account_balance_range.end() ||
previous_distribution_account_balance_iter->dividend_payout_asset_type < current_distribution_account_balance_iter->second->asset_type)
{
// there are no more current balances or there is no current balance for this particular previous asset type
@ -1087,7 +1508,7 @@ void schedule_pending_dividend_balances(database& db,
share_type delta_balance = current_balance - previous_balance;
// Next, figure out if we want to share this out -- if the amount added to the distribution
// Next, figure out if we want to share this out -- if the amount added to the distribution
// account since last payout is too small, we won't bother.
share_type total_fee_per_asset_in_payout_asset;
@ -1096,7 +1517,7 @@ void schedule_pending_dividend_balances(database& db,
{
payout_asset_object = &db.get_core_asset();
total_fee_per_asset_in_payout_asset = total_fee_per_asset_in_core;
dlog("Fee for distributing ${payout_asset_type}: ${fee}",
dlog("Fee for distributing ${payout_asset_type}: ${fee}",
("payout_asset_type", asset_id_type()(db).symbol)
("fee", asset(total_fee_per_asset_in_core, asset_id_type())));
}
@ -1112,7 +1533,7 @@ void schedule_pending_dividend_balances(database& db,
FC_ASSERT(total_fee_per_asset.asset_id == payout_asset_type);
total_fee_per_asset_in_payout_asset = total_fee_per_asset.amount;
dlog("Fee for distributing ${payout_asset_type}: ${fee}",
dlog("Fee for distributing ${payout_asset_type}: ${fee}",
("payout_asset_type", payout_asset_type(db).symbol)("fee", total_fee_per_asset_in_payout_asset));
}
@ -1125,7 +1546,7 @@ void schedule_pending_dividend_balances(database& db,
wdump((total_fee_per_asset_in_payout_asset)(dividend_data.options));
minimum_shares_to_distribute = minimum_amount_to_distribute;
}
dlog("Processing dividend payments of asset type ${payout_asset_type}, delta balance is ${delta_balance}", ("payout_asset_type", payout_asset_type(db).symbol)("delta_balance", delta_balance));
if (delta_balance > 0)
{
@ -1138,7 +1559,7 @@ void schedule_pending_dividend_balances(database& db,
db.modify(asset_dynamic_data_id_type()(db), [total_fee_per_asset_in_core](asset_dynamic_data_object& d) {
d.accumulated_fees += total_fee_per_asset_in_core;
});
db.adjust_balance(dividend_data.dividend_distribution_account,
db.adjust_balance(dividend_data.dividend_distribution_account,
asset(-total_fee_per_asset_in_core, asset_id_type()));
delta_balance -= total_fee_per_asset_in_core;
}
@ -1153,7 +1574,7 @@ void schedule_pending_dividend_balances(database& db,
("need", asset(total_fee_per_asset_in_core, asset_id_type()))
("have", asset(dynamic_data.fee_pool, payout_asset_type)));
// deduct the fee from the dividend distribution account
db.adjust_balance(dividend_data.dividend_distribution_account,
db.adjust_balance(dividend_data.dividend_distribution_account,
asset(-total_fee_per_asset_in_payout_asset, payout_asset_type));
// convert it to core
db.modify(payout_asset_object->dynamic_data(db), [total_fee_per_asset_in_core, total_fee_per_asset_in_payout_asset](asset_dynamic_data_object& d) {
@ -1167,7 +1588,7 @@ void schedule_pending_dividend_balances(database& db,
delta_balance -= total_fee_per_asset_in_payout_asset;
}
dlog("There are ${count} holders of the dividend-paying asset, with a total balance of ${total}",
dlog("There are ${count} holders of the dividend-paying asset, with a total balance of ${total}",
("count", holder_account_count)
("total", total_balance_of_dividend_asset));
share_type remaining_amount_to_distribute = delta_balance;
@ -1239,7 +1660,7 @@ void schedule_pending_dividend_balances(database& db,
dlog("Pending payout: ${account_name} -> ${amount}",
("account_name", pending_payout.owner(db).name)
("amount", asset(pending_payout.pending_balance, pending_payout.dividend_payout_asset_type)));
dlog("Remaining balance not paid out: ${amount}",
dlog("Remaining balance not paid out: ${amount}",
("amount", asset(remaining_amount_to_distribute, payout_asset_type)));
share_type distributed_amount = delta_balance - remaining_amount_to_distribute;
@ -1269,7 +1690,7 @@ void schedule_pending_dividend_balances(database& db,
// This should be extremely rare (caused by an override transfer by the asset owner).
// Reduce all pending payouts proportionally
share_type total_pending_balances;
auto pending_payouts_range =
auto pending_payouts_range =
pending_payout_balance_index.indices().get<by_dividend_payout_account>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id, payout_asset_type));
for (const pending_dividend_payout_balance_for_holder_object& pending_balance_object : boost::make_iterator_range(pending_payouts_range.first, pending_payouts_range.second))
@ -1306,10 +1727,10 @@ void schedule_pending_dividend_balances(database& db,
}
// iterate
if (previous_distribution_account_balance_iter == previous_distribution_account_balance_range.second ||
if (previous_distribution_account_balance_iter == previous_distribution_account_balance_range.second ||
current_distribution_account_balance_iter->second->asset_type < previous_distribution_account_balance_iter->dividend_payout_asset_type)
++current_distribution_account_balance_iter;
else if (current_distribution_account_balance_iter == current_distribution_account_balance_range.end() ||
else if (current_distribution_account_balance_iter == current_distribution_account_balance_range.end() ||
previous_distribution_account_balance_iter->dividend_payout_asset_type < current_distribution_account_balance_iter->second->asset_type)
++previous_distribution_account_balance_iter;
else
@ -1351,7 +1772,7 @@ void process_dividend_assets(database& db)
{
try
{
dlog("Dividend payout time has arrived for asset ${holder_asset}",
dlog("Dividend payout time has arrived for asset ${holder_asset}",
("holder_asset", dividend_holder_asset_obj.symbol));
#ifndef NDEBUG
// dump balances before the payouts for debugging
@ -1363,14 +1784,14 @@ void process_dividend_assets(database& db)
// when we do the payouts, we first increase the balances in all of the receiving accounts
// and use this map to keep track of the total amount of each asset paid out.
// Afterwards, we decrease the distribution account's balance by the total amount paid out,
// Afterwards, we decrease the distribution account's balance by the total amount paid out,
// and modify the distributed_balances accordingly
std::map<asset_id_type, share_type> amounts_paid_out_by_asset;
auto pending_payouts_range =
auto pending_payouts_range =
pending_payout_balance_index.indices().get<by_dividend_account_payout>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id));
// the pending_payouts_range is all payouts for this dividend asset, sorted by the holder's account
// we iterate in this order so we can build up a list of payouts for each account to put in the
// we iterate in this order so we can build up a list of payouts for each account to put in the
// virtual op
vector<asset> payouts_for_this_holder;
fc::optional<account_id_type> last_holder_account_id;
@ -1382,7 +1803,7 @@ void process_dividend_assets(database& db)
auto approved_assets_iter = approved_assets.find(asset_id);
if (approved_assets_iter != approved_assets.end())
return approved_assets_iter->second;
bool is_approved = is_authorized_asset(db, dividend_distribution_account_object,
bool is_approved = is_authorized_asset(db, dividend_distribution_account_object,
asset_id(db));
approved_assets[asset_id] = is_approved;
return is_approved;
@ -1395,8 +1816,8 @@ void process_dividend_assets(database& db)
if (last_holder_account_id && *last_holder_account_id != pending_balance_object.owner && payouts_for_this_holder.size())
{
// we've moved on to a new account, generate the dividend payment virtual op for the previous one
db.push_applied_operation(asset_dividend_distribution_operation(dividend_holder_asset_obj.id,
*last_holder_account_id,
db.push_applied_operation(asset_dividend_distribution_operation(dividend_holder_asset_obj.id,
*last_holder_account_id,
payouts_for_this_holder));
dlog("Just pushed virtual op for payout to ${account}", ("account", (*last_holder_account_id)(db).name));
payouts_for_this_holder.clear();
@ -1408,14 +1829,14 @@ void process_dividend_assets(database& db)
is_authorized_asset(db, pending_balance_object.owner(db), pending_balance_object.dividend_payout_asset_type(db)) &&
is_asset_approved_for_distribution_account(pending_balance_object.dividend_payout_asset_type))
{
dlog("Processing payout of ${asset} to account ${account}",
dlog("Processing payout of ${asset} to account ${account}",
("asset", asset(pending_balance_object.pending_balance, pending_balance_object.dividend_payout_asset_type))
("account", pending_balance_object.owner(db).name));
db.adjust_balance(pending_balance_object.owner,
asset(pending_balance_object.pending_balance,
asset(pending_balance_object.pending_balance,
pending_balance_object.dividend_payout_asset_type));
payouts_for_this_holder.push_back(asset(pending_balance_object.pending_balance,
payouts_for_this_holder.push_back(asset(pending_balance_object.pending_balance,
pending_balance_object.dividend_payout_asset_type));
last_holder_account_id = pending_balance_object.owner;
amounts_paid_out_by_asset[pending_balance_object.dividend_payout_asset_type] += pending_balance_object.pending_balance;
@ -1431,8 +1852,8 @@ void process_dividend_assets(database& db)
if (last_holder_account_id && payouts_for_this_holder.size())
{
// we've moved on to a new account, generate the dividend payment virtual op for the previous one
db.push_applied_operation(asset_dividend_distribution_operation(dividend_holder_asset_obj.id,
*last_holder_account_id,
db.push_applied_operation(asset_dividend_distribution_operation(dividend_holder_asset_obj.id,
*last_holder_account_id,
payouts_for_this_holder));
dlog("Just pushed virtual op for payout to ${account}", ("account", (*last_holder_account_id)(db).name));
}
@ -1445,11 +1866,11 @@ void process_dividend_assets(database& db)
const asset_id_type& asset_paid_out = value.first;
const share_type& amount_paid_out = value.second;
db.adjust_balance(dividend_data.dividend_distribution_account,
db.adjust_balance(dividend_data.dividend_distribution_account,
asset(-amount_paid_out,
asset_paid_out));
auto distributed_balance_iter =
distributed_dividend_balance_index.indices().get<by_dividend_payout_asset>().find(boost::make_tuple(dividend_holder_asset_obj.id,
auto distributed_balance_iter =
distributed_dividend_balance_index.indices().get<by_dividend_payout_asset>().find(boost::make_tuple(dividend_holder_asset_obj.id,
asset_paid_out));
assert(distributed_balance_iter != distributed_dividend_balance_index.indices().get<by_dividend_payout_asset>().end());
if (distributed_balance_iter != distributed_dividend_balance_index.indices().get<by_dividend_payout_asset>().end())
@ -1466,7 +1887,7 @@ void process_dividend_assets(database& db)
fc::optional<fc::time_point_sec> next_payout_time;
if (dividend_data_obj.options.payout_interval)
{
// if there was a previous payout, make our next payment one interval
// if there was a previous payout, make our next payment one interval
uint32_t current_time_sec = current_head_block_time.sec_since_epoch();
uint32_t next_possible_time_sec = dividend_data_obj.last_scheduled_payout_time->sec_since_epoch();
do
@ -1480,12 +1901,102 @@ void process_dividend_assets(database& db)
(dividend_data_obj.last_payout_time)
(dividend_data_obj.options.next_payout_time));
});
}
}
FC_RETHROW_EXCEPTIONS(error, "Error while paying out dividends for holder asset ${holder_asset}", ("holder_asset", dividend_holder_asset_obj.symbol))
}
}
} FC_CAPTURE_AND_RETHROW() }
void database::perform_son_tasks()
{
const global_property_object& gpo = get_global_properties();
if(gpo.parameters.son_account() == GRAPHENE_NULL_ACCOUNT && head_block_time() >= HARDFORK_SON_TIME)
{
const auto& son_account = create<account_object>([&](account_object& a) {
a.name = "son-account";
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 0;
a.registrar = a.lifetime_referrer = a.referrer = a.id;
a.membership_expiration_date = time_point_sec::maximum();
a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
});
modify( gpo, [&son_account]( global_property_object& gpo ) {
gpo.parameters.extensions.value.son_account = son_account.get_id();
if( gpo.pending_parameters )
gpo.pending_parameters->extensions.value.son_account = son_account.get_id();
});
}
// create BTC asset here because son_account is the issuer of the BTC
if (gpo.parameters.btc_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_TIME)
{
const asset_dynamic_data_object& dyn_asset =
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
a.current_supply = 0;
});
const asset_object& btc_asset =
create<asset_object>( [&gpo, &dyn_asset]( asset_object& a ) {
a.symbol = "BTC";
a.precision = 8;
a.issuer = gpo.parameters.son_account();
a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
a.options.market_fee_percent = 500; // 5%
a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
a.options.flags = asset_issuer_permission_flags::charge_market_fee |
//asset_issuer_permission_flags::white_list |
asset_issuer_permission_flags::override_authority |
asset_issuer_permission_flags::transfer_restricted |
asset_issuer_permission_flags::disable_confidential;
a.options.core_exchange_rate.base.amount = 100000;
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value
a.options.core_exchange_rate.quote.asset_id = a.id;
a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty
a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set
a.options.whitelist_markets.clear(); // might be traded with
a.options.blacklist_markets.clear(); // might not be traded with
a.dynamic_asset_data_id = dyn_asset.id;
});
modify( gpo, [&btc_asset]( global_property_object& gpo ) {
gpo.parameters.extensions.value.btc_asset = btc_asset.get_id();
if( gpo.pending_parameters )
gpo.pending_parameters->extensions.value.btc_asset = btc_asset.get_id();
});
}
// Pay the SONs
if (head_block_time() >= HARDFORK_SON_TIME)
{
// Before making a budget we should pay out SONs
// This function should check if its time to pay sons
// and modify the global son funds accordingly, whatever is left is passed on to next budget
pay_sons();
}
}
void update_son_params(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;
});
}
db.modify( gpo, []( global_property_object& gpo ) {
gpo.parameters.extensions.value.maximum_son_count = 7;
});
}
}
void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props)
{ try {
const auto& gpo = get_global_properties();
@ -1497,6 +2008,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
rolling_period_start(*this);
update_son_params(*this);
struct vote_tally_helper {
database& d;
const global_property_object& props;
@ -1508,6 +2021,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
d._vote_tally_buffer.resize(props.next_available_vote_id);
d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1);
d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1);
d._son_count_histogram_buffer.resize(props.parameters.maximum_son_count() / 2 + 1);
d._total_voting_stake = 0;
auto balance_type = vesting_balance_type::normal;
@ -1619,6 +2133,18 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
// same rationale as for witnesses
d._committee_count_histogram_buffer[offset] += voting_stake;
}
if( opinion_account.options.num_son <= props.parameters.maximum_son_count() )
{
uint16_t offset = std::min(size_t(opinion_account.options.num_son/2),
d._son_count_histogram_buffer.size() - 1);
// votes for a number greater than maximum_son_count
// are turned into votes for maximum_son_count.
//
// in particular, this takes care of the case where a
// member was voting for a high number, then the
// parameter was lowered.
d._son_count_histogram_buffer[offset] += voting_stake;
}
d._total_voting_stake += voting_stake;
}
@ -1634,11 +2160,14 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
};
clear_canary a(_witness_count_histogram_buffer),
b(_committee_count_histogram_buffer),
d(_son_count_histogram_buffer),
c(_vote_tally_buffer);
perform_son_tasks();
update_top_n_authorities(*this);
update_active_witnesses();
update_active_committee_members();
update_active_sons();
update_worker_votes();
const dynamic_global_property_object& dgpo = get_dynamic_global_properties();
@ -1668,6 +2197,38 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
p.pending_parameters->extensions.value.gpos_subperiod = p.parameters.extensions.value.gpos_subperiod;
if( !p.pending_parameters->extensions.value.gpos_vesting_lockin_period.valid() )
p.pending_parameters->extensions.value.gpos_vesting_lockin_period = p.parameters.extensions.value.gpos_vesting_lockin_period;
if( !p.pending_parameters->extensions.value.rbac_max_permissions_per_account.valid() )
p.pending_parameters->extensions.value.rbac_max_permissions_per_account = p.parameters.extensions.value.rbac_max_permissions_per_account;
if( !p.pending_parameters->extensions.value.rbac_max_account_authority_lifetime.valid() )
p.pending_parameters->extensions.value.rbac_max_account_authority_lifetime = p.parameters.extensions.value.rbac_max_account_authority_lifetime;
if( !p.pending_parameters->extensions.value.rbac_max_authorities_per_permission.valid() )
p.pending_parameters->extensions.value.rbac_max_authorities_per_permission = p.parameters.extensions.value.rbac_max_authorities_per_permission;
if( !p.pending_parameters->extensions.value.account_roles_max_per_account.valid() )
p.pending_parameters->extensions.value.account_roles_max_per_account = p.parameters.extensions.value.account_roles_max_per_account;
if( !p.pending_parameters->extensions.value.account_roles_max_lifetime.valid() )
p.pending_parameters->extensions.value.account_roles_max_lifetime = p.parameters.extensions.value.account_roles_max_lifetime;
if( !p.pending_parameters->extensions.value.son_vesting_amount.valid() )
p.pending_parameters->extensions.value.son_vesting_amount = p.parameters.extensions.value.son_vesting_amount;
if( !p.pending_parameters->extensions.value.son_vesting_period.valid() )
p.pending_parameters->extensions.value.son_vesting_period = p.parameters.extensions.value.son_vesting_period;
if( !p.pending_parameters->extensions.value.son_pay_max.valid() )
p.pending_parameters->extensions.value.son_pay_max = p.parameters.extensions.value.son_pay_max;
if( !p.pending_parameters->extensions.value.son_pay_time.valid() )
p.pending_parameters->extensions.value.son_pay_time = p.parameters.extensions.value.son_pay_time;
if( !p.pending_parameters->extensions.value.son_deregister_time.valid() )
p.pending_parameters->extensions.value.son_deregister_time = p.parameters.extensions.value.son_deregister_time;
if( !p.pending_parameters->extensions.value.son_heartbeat_frequency.valid() )
p.pending_parameters->extensions.value.son_heartbeat_frequency = p.parameters.extensions.value.son_heartbeat_frequency;
if( !p.pending_parameters->extensions.value.son_down_time.valid() )
p.pending_parameters->extensions.value.son_down_time = p.parameters.extensions.value.son_down_time;
if( !p.pending_parameters->extensions.value.son_bitcoin_min_tx_confirmations.valid() )
p.pending_parameters->extensions.value.son_bitcoin_min_tx_confirmations = p.parameters.extensions.value.son_bitcoin_min_tx_confirmations;
if( !p.pending_parameters->extensions.value.son_account.valid() )
p.pending_parameters->extensions.value.son_account = p.parameters.extensions.value.son_account;
if( !p.pending_parameters->extensions.value.btc_asset.valid() )
p.pending_parameters->extensions.value.btc_asset = p.parameters.extensions.value.btc_asset;
if( !p.pending_parameters->extensions.value.maximum_son_count.valid() )
p.pending_parameters->extensions.value.maximum_son_count = p.parameters.extensions.value.maximum_son_count;
p.parameters = std::move(*p.pending_parameters);
p.pending_parameters.reset();
}
@ -1717,8 +2278,9 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
modify( d, [](asset_bitasset_data_object& o) { o.force_settled_volume = 0; });
// Ideally we have to do this after every block but that leads to longer block applicaiton/replay times.
// So keep it here as it is not critical. valid_to check ensures
// these custom account auths are not usable.
// these custom account auths and account roles are not usable.
clear_expired_custom_account_authorities(*this);
clear_expired_account_roles(*this);
// process_budget needs to run at the bottom because
// it needs to know the next_maintenance_time
process_budget();

View file

@ -48,6 +48,7 @@
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/nft_object.hpp>
using namespace fc;
using namespace graphene::chain;
@ -55,8 +56,13 @@ using namespace graphene::chain;
struct get_impacted_account_visitor
{
flat_set<account_id_type>& _impacted;
get_impacted_account_visitor( flat_set<account_id_type>& impact ):_impacted(impact) {}
typedef void result_type;
bool _ignore_custom_op_reqd_auths;
get_impacted_account_visitor( flat_set<account_id_type>& impact, bool ignore_custom_operation_required_auths )
: _impacted( impact ), _ignore_custom_op_reqd_auths( ignore_custom_operation_required_auths )
{}
using result_type = void;
void operator()( const transfer_operation& op )
{
@ -142,7 +148,7 @@ struct get_impacted_account_visitor
{
vector<authority> other;
for( const auto& proposed_op : op.proposed_ops )
operation_get_required_authorities( proposed_op.op, _impacted, _impacted, other );
operation_get_required_authorities( proposed_op.op, _impacted, _impacted, other, _ignore_custom_op_reqd_auths );
for( auto& o : other )
add_authority_accounts( _impacted, o );
}
@ -350,22 +356,85 @@ struct get_impacted_account_visitor
void operator()( const finalize_offer_operation& op ) {
_impacted.insert( op.fee_paying_account );
}
void operator()( const account_role_create_operation& op ){
_impacted.insert( op.owner );
}
void operator()( const account_role_update_operation& op ){
_impacted.insert( op.owner );
}
void operator()( const account_role_delete_operation& op ){
_impacted.insert( op.owner );
}
void operator()( const son_create_operation& op ) {
_impacted.insert( op.owner_account );
}
void operator()( const son_update_operation& op ) {
_impacted.insert( op.owner_account );
}
void operator()( const son_deregister_operation& op ) {
_impacted.insert( op.payer);
}
void operator()( const son_heartbeat_operation& op ) {
_impacted.insert( op.owner_account );
}
void operator()( const son_report_down_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const son_maintenance_operation& op ) {
_impacted.insert( op.owner_account );
}
void operator()( const son_wallet_recreate_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const son_wallet_update_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const son_wallet_deposit_create_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const son_wallet_deposit_process_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const son_wallet_withdraw_create_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const son_wallet_withdraw_process_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_address_add_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_address_update_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_address_delete_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_transaction_create_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_transaction_sign_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_transaction_send_operation& op ) {
_impacted.insert( op.payer );
}
void operator()( const sidechain_transaction_settle_operation& op ) {
_impacted.insert( op.payer );
}
};
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
{
get_impacted_account_visitor vtor = get_impacted_account_visitor( result );
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result, bool ignore_custom_operation_required_auths ) {
get_impacted_account_visitor vtor = get_impacted_account_visitor( result, ignore_custom_operation_required_auths );
op.visit( vtor );
}
void graphene::chain::transaction_get_impacted_accounts( const transaction& tx, flat_set<account_id_type>& result )
{
void graphene::chain::transaction_get_impacted_accounts( const transaction& tx, flat_set<account_id_type>& result, bool ignore_custom_operation_required_auths ) {
for( const auto& op : tx.operations )
operation_get_impacted_accounts( op, result );
operation_get_impacted_accounts( op, result, ignore_custom_operation_required_auths );
}
void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )
{
void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts, bool ignore_custom_operation_required_auths ) {
if( obj->id.space() == protocol_ids )
{
switch( (object_type)obj->id.type() )
@ -411,12 +480,14 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
} case proposal_object_type:{
const auto& aobj = dynamic_cast<const proposal_object*>(obj);
assert( aobj != nullptr );
transaction_get_impacted_accounts( aobj->proposed_transaction, accounts );
transaction_get_impacted_accounts( aobj->proposed_transaction, accounts,
ignore_custom_operation_required_auths);
break;
} case operation_history_object_type:{
const auto& aobj = dynamic_cast<const operation_history_object*>(obj);
assert( aobj != nullptr );
operation_get_impacted_accounts( aobj->op, accounts );
operation_get_impacted_accounts( aobj->op, accounts,
ignore_custom_operation_required_auths);
break;
} case withdraw_permission_object_type:{
const auto& aobj = dynamic_cast<const withdraw_permission_object*>(obj);
@ -515,6 +586,30 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
accounts.insert(aobj->approved);
accounts.insert(aobj->approved_operators.begin(), aobj->approved_operators.end());
break;
} case account_role_object_type:{
const auto& aobj = dynamic_cast<const account_role_object*>(obj);
assert( aobj != nullptr );
accounts.insert( aobj->owner );
accounts.insert( aobj->whitelisted_accounts.begin(), aobj->whitelisted_accounts.end() );
break;
} case son_object_type:{
const auto& aobj = dynamic_cast<const son_object*>(obj);
assert( aobj != nullptr );
accounts.insert( aobj->son_account );
break;
} case son_wallet_object_type:{
break;
} case son_wallet_deposit_object_type:{
break;
} case son_wallet_withdraw_object_type:{
break;
} case sidechain_address_object_type:{
const auto& aobj = dynamic_cast<const sidechain_address_object*>(obj);
assert( aobj != nullptr );
accounts.insert( aobj->sidechain_address_account );
break;
} case sidechain_transaction_object_type:{
break;
}
}
}
@ -545,7 +640,8 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
} case impl_transaction_history_object_type:{
const auto& aobj = dynamic_cast<const transaction_history_object*>(obj);
FC_ASSERT( aobj != nullptr );
transaction_get_impacted_accounts( aobj->trx, accounts );
transaction_get_impacted_accounts( aobj->trx, accounts,
ignore_custom_operation_required_auths);
break;
} case impl_blinded_balance_object_type:{
const auto& aobj = dynamic_cast<const blinded_balance_object*>(obj);
@ -624,6 +720,7 @@ void database::notify_changed_objects()
if( _undo_db.enabled() )
{
const auto& head_undo = _undo_db.head();
auto chain_time = head_block_time();
// New
if( !new_objects.empty() )
@ -635,7 +732,8 @@ void database::notify_changed_objects()
new_ids.push_back(item);
auto obj = find_object(item);
if(obj != nullptr)
get_relevant_accounts(obj, new_accounts_impacted);
get_relevant_accounts(obj, new_accounts_impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time));
}
GRAPHENE_TRY_NOTIFY( new_objects, new_ids, new_accounts_impacted)
@ -649,7 +747,8 @@ void database::notify_changed_objects()
for( const auto& item : head_undo.old_values )
{
changed_ids.push_back(item.first);
get_relevant_accounts(item.second.get(), changed_accounts_impacted);
get_relevant_accounts(item.second.get(), changed_accounts_impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time));
}
GRAPHENE_TRY_NOTIFY( changed_objects, changed_ids, changed_accounts_impacted)
@ -666,7 +765,8 @@ void database::notify_changed_objects()
removed_ids.emplace_back( item.first );
auto obj = item.second.get();
removed.emplace_back( obj );
get_relevant_accounts(obj, removed_accounts_impacted);
get_relevant_accounts(obj, removed_accounts_impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time));
}
GRAPHENE_TRY_NOTIFY( removed_objects, removed_ids, removed, removed_accounts_impacted)

View file

@ -223,6 +223,7 @@ void database::clear_expired_proposals()
elog("Failed to apply proposed transaction on its expiration. Deleting it.\n${proposal}\n${error}",
("proposal", proposal)("error", e.to_detail_string()));
}
remove_son_proposal(proposal);
remove(proposal);
}
}
@ -728,5 +729,50 @@ void database::finalize_expired_offers(){
}
});
} FC_CAPTURE_AND_RETHROW()}
void database::remove_son_proposal( const proposal_object& proposal )
{ try {
if( proposal.proposed_transaction.operations.size() == 1 &&
( proposal.proposed_transaction.operations.back().which() == operation::tag<son_deregister_operation>::value ||
proposal.proposed_transaction.operations.back().which() == operation::tag<son_report_down_operation>::value) )
{
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get<by_proposal>();
auto son_proposal_itr = son_proposal_idx.find( proposal.id );
if( son_proposal_itr == son_proposal_idx.end() ) {
return;
}
remove( *son_proposal_itr );
}
} FC_CAPTURE_AND_RETHROW( (proposal) ) }
void database::remove_inactive_son_down_proposals( const vector<son_id_type>& son_ids_to_remove )
{
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get< by_id >();
std::vector<proposal_id_type> proposals_to_remove;
for( auto& son_proposal : son_proposal_idx )
{
if(son_proposal.proposal_type == son_proposal_type::son_report_down_proposal)
{
auto it = std::find(son_ids_to_remove.begin(), son_ids_to_remove.end(), son_proposal.son_id);
if (it != son_ids_to_remove.end())
{
ilog( "Removing inactive proposal ${p} for son ${s}", ("p", son_proposal.proposal_id) ("s",son_proposal.son_id));
proposals_to_remove.push_back(son_proposal.proposal_id);
}
}
}
for( auto& proposal_id : proposals_to_remove )
{
const auto& proposal_obj = proposal_id(*this);
remove_son_proposal(proposal_obj);
remove(proposal_obj);
}
}
void database::remove_inactive_son_proposals( const vector<son_id_type>& son_ids_to_remove )
{
remove_inactive_son_down_proposals( son_ids_to_remove );
}
} }

View file

@ -22,10 +22,12 @@
* THE SOFTWARE.
*/
#include <graphene/protocol/son_info.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/global_property_object.hpp>
#include <graphene/chain/witness_object.hpp>
#include <graphene/chain/witness_schedule_object.hpp>
#include <graphene/chain/son_object.hpp>
#include <fc/popcount.hpp>
@ -74,6 +76,47 @@ witness_id_type database::get_scheduled_witness( uint32_t slot_num )const
return wid;
}
son_id_type database::get_scheduled_son( uint32_t slot_num )const
{
son_id_type sid;
const global_property_object& gpo = get_global_properties();
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
{
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
const son_schedule_object& sso = son_schedule_id_type()(*this);
uint64_t current_aslot = dpo.current_aslot + slot_num;
return sso.current_shuffled_sons[ current_aslot % sso.current_shuffled_sons.size() ];
}
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM &&
slot_num != 0 )
{
const son_schedule_object& sso = son_schedule_id_type()(*this);
// ask the near scheduler who goes in the given slot
bool slot_is_near = sso.scheduler.get_slot(slot_num-1, sid);
if(! slot_is_near)
{
// if the near scheduler doesn't know, we have to extend it to
// a far scheduler.
// n.b. instantiating it is slow, but block gaps long enough to
// need it are likely pretty rare.
witness_scheduler_rng far_rng(sso.rng_seed.begin(), GRAPHENE_FAR_SCHEDULE_CTR_IV);
far_future_son_scheduler far_scheduler =
far_future_son_scheduler(sso.scheduler, far_rng);
if(!far_scheduler.get_slot(slot_num-1, sid))
{
// no scheduled son -- somebody set up us the bomb
// n.b. this code path is impossible, the present
// implementation of far_future_son_scheduler
// returns true unconditionally
assert( false );
}
}
}
return sid;
}
fc::time_point_sec database::get_slot_time(uint32_t slot_num)const
{
if( slot_num == 0 )
@ -148,6 +191,41 @@ void database::update_witness_schedule()
}
}
void database::update_son_schedule()
{
const son_schedule_object& sso = son_schedule_id_type()(*this);
const global_property_object& gpo = get_global_properties();
if( head_block_num() % gpo.active_sons.size() == 0 )
{
modify( sso, [&]( son_schedule_object& _sso )
{
_sso.current_shuffled_sons.clear();
_sso.current_shuffled_sons.reserve( gpo.active_sons.size() );
for( const son_info& w : gpo.active_sons )
_sso.current_shuffled_sons.push_back( w.son_id );
auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32;
for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i )
{
/// High performance random generator
/// http://xorshift.di.unimi.it/
uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL;
k ^= (k >> 12);
k ^= (k << 25);
k ^= (k >> 27);
k *= 2685821657736338717ULL;
uint32_t jmax = _sso.current_shuffled_sons.size() - i;
uint32_t j = i + k%jmax;
std::swap( _sso.current_shuffled_sons[i],
_sso.current_shuffled_sons[j] );
}
});
}
}
vector<witness_id_type> database::get_near_witness_schedule()const
{
const witness_schedule_object& wso = get_witness_schedule_object();
@ -228,6 +306,71 @@ void database::update_witness_schedule(const signed_block& next_block)
idump( ( double(total_time/1000000.0)/calls) );
}
void database::update_son_schedule(const signed_block& next_block)
{
auto start = fc::time_point::now();
const global_property_object& gpo = get_global_properties();
const son_schedule_object& sso = get(son_schedule_id_type());
uint32_t schedule_needs_filled = gpo.active_sons.size();
uint32_t schedule_slot = get_slot_at_time(next_block.timestamp);
// We shouldn't be able to generate _pending_block with timestamp
// in the past, and incoming blocks from the network with timestamp
// in the past shouldn't be able to make it this far without
// triggering FC_ASSERT elsewhere
assert( schedule_slot > 0 );
son_id_type first_son;
bool slot_is_near = sso.scheduler.get_slot( schedule_slot-1, first_son );
son_id_type son;
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
assert( dpo.random.data_size() == witness_scheduler_rng::seed_length );
assert( witness_scheduler_rng::seed_length == sso.rng_seed.size() );
modify(sso, [&](son_schedule_object& _sso)
{
_sso.slots_since_genesis += schedule_slot;
witness_scheduler_rng rng(sso.rng_seed.data(), _sso.slots_since_genesis);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.size()) / 2, 1);
if( slot_is_near )
{
uint32_t drain = schedule_slot;
while( drain > 0 )
{
if( _sso.scheduler.size() == 0 )
break;
_sso.scheduler.consume_schedule();
--drain;
}
}
else
{
_sso.scheduler.reset_schedule( first_son );
}
while( !_sso.scheduler.get_slot(schedule_needs_filled, son) )
{
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
}
_sso.last_scheduling_block = next_block.block_num();
_sso.recent_slots_filled = (
(_sso.recent_slots_filled << 1)
+ 1) << (schedule_slot - 1);
});
auto end = fc::time_point::now();
static uint64_t total_time = 0;
static uint64_t calls = 0;
total_time += (end - start).count();
if( ++calls % 1000 == 0 )
idump( ( double(total_time/1000000.0)/calls) );
}
uint32_t database::update_witness_missed_blocks( const signed_block& b )
{
uint32_t missed_blocks = get_slot_at_time( b.timestamp );

View file

@ -107,6 +107,11 @@ fc::variant_object get_config()
result[ "GRAPHENE_RELAXED_COMMITTEE_ACCOUNT" ] = fc::variant(GRAPHENE_RELAXED_COMMITTEE_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_NULL_ACCOUNT" ] = fc::variant(GRAPHENE_NULL_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_TEMP_ACCOUNT" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_PROXY_TO_SELF_ACCOUNT" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_RAKE_FEE_ACCOUNT_ID" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_NULL_WITNESS" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_DEFAULT_RAKE_FEE_PERCENTAGE" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
return result;
}

View file

@ -1,3 +1,3 @@
#ifndef HARDFORK_1000_TIME
#define HARDFORK_1000_TIME (fc::time_point_sec( 1540000000 ))
#define HARDFORK_1000_TIME (fc::time_point_sec( 1550491200 ))
#endif

View file

@ -1,4 +1,4 @@
// added delete sport and delete event group operations
#ifndef HARDFORK_1001_TIME
#define HARDFORK_1001_TIME (fc::time_point_sec( 1540000000 ))
#define HARDFORK_1001_TIME (fc::time_point_sec( 1550491200 ))
#endif

View file

@ -1,4 +1,4 @@
// 5050_1 HARDFORK Thursday, 15 April 2020 20:00:00 GMT
// 5050_1 HARDFORK Thursday, 22 April 2020 20:00:00 GMT
#ifndef HARDFORK_5050_1_TIME
#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1586980800 ))
#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1587585600 ))
#endif

View file

@ -1,4 +1,4 @@
// Placeholder HF for affiliate reward system
#ifndef HARDFORK_999_TIME
#define HARDFORK_999_TIME (fc::time_point_sec( 1540000000 ))
#define HARDFORK_999_TIME (fc::time_point_sec( 1550491200 ))
#endif

View file

@ -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( 1566784800 ))
#define HARDFORK_CORE_429_TIME (fc::time_point_sec( 1568340000 ))
#endif

View file

@ -0,0 +1,6 @@
// #210 Check authorities on custom_operation
#ifndef HARDFORK_CORE_210_TIME
#define HARDFORK_CORE_210_TIME (fc::time_point_sec(1893456000)) // Jan 1 00:00:00 2030 (Not yet scheduled)
// Bugfix: pre-HF 210, custom_operation's required_auths field was ignored.
#define MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time) (chain_time <= HARDFORK_CORE_210_TIME)
#endif

View file

@ -1,4 +1,4 @@
// GPOS HARDFORK Monday, 6 January 2020 01:00:00 GMT
// GPOS HARDFORK Monday, 17 February 2020 22:00:00 GMT
#ifndef HARDFORK_GPOS_TIME
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1578272400 ))
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1581976800 ))
#endif

View file

@ -1,4 +1,4 @@
// NFT HARDFORK Sat, 15-Aug-20 00:00:00 UTC
// GPOS HARDFORK 2020-12-21 00:00:00 GMT
#ifndef HARDFORK_NFT_TIME
#define HARDFORK_NFT_TIME (fc::time_point_sec( 1597449600 ))
#define HARDFORK_NFT_TIME (fc::time_point_sec( 1608508800 ))
#endif

View file

@ -0,0 +1,4 @@
// GPOS HARDFORK 2020-12-21 00:00:00 GMT
#ifndef HARDFORK_SON_TIME
#define HARDFORK_SON_TIME (fc::time_point_sec( 1608508800 ))
#endif

View file

@ -0,0 +1,4 @@
// SON2 HARDFORK Saturday, July 31, 2021 00:00:00 GMT
#ifndef HARDFORK_SON2_TIME
#define HARDFORK_SON2_TIME (fc::time_point_sec( 1627689600 ))
#endif

View file

@ -1,3 +1,3 @@
#ifndef HARDFORK_SWEEPS_TIME
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1566784800 ))
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1568340000 ))
#endif

View file

@ -0,0 +1,35 @@
#pragma once
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/protocol/operations.hpp>
#include <graphene/protocol/types.hpp>
namespace graphene { namespace chain {
class account_role_create_evaluator : public evaluator<account_role_create_evaluator>
{
public:
typedef account_role_create_operation operation_type;
void_result do_evaluate( const account_role_create_operation& o );
object_id_type do_apply( const account_role_create_operation& o );
};
class account_role_update_evaluator : public evaluator<account_role_update_evaluator>
{
public:
typedef account_role_update_operation operation_type;
void_result do_evaluate( const account_role_update_operation& o );
void_result do_apply( const account_role_update_operation& o );
};
class account_role_delete_evaluator : public evaluator<account_role_delete_evaluator>
{
public:
typedef account_role_delete_operation operation_type;
void_result do_evaluate( const account_role_delete_operation& o );
void_result do_apply( const account_role_delete_operation& o );
};
} } // graphene::chain

View file

@ -0,0 +1,51 @@
#pragma once
#include <graphene/protocol/types.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
namespace graphene
{
namespace chain
{
using namespace graphene::db;
class account_role_object : public abstract_object<account_role_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = account_role_object_type;
account_id_type owner;
std::string name;
std::string metadata;
flat_set<int> allowed_operations;
flat_set<account_id_type> whitelisted_accounts;
time_point_sec valid_to;
};
struct by_owner;
struct by_expiration;
using account_role_multi_index_type = multi_index_container<
account_role_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_non_unique< tag<by_owner>,
member<account_role_object, account_id_type, &account_role_object::owner>
>,
ordered_unique< tag<by_expiration>,
composite_key<account_role_object,
member<account_role_object, time_point_sec, &account_role_object::valid_to>,
member<object, object_id_type, &object::id>>
>
>
>;
using account_role_index = generic_index<account_role_object, account_role_multi_index_type>;
} // namespace chain
} // namespace graphene
MAP_OBJECT_ID_TO_TYPE(graphene::chain::account_role_object)
FC_REFLECT_DERIVED(graphene::chain::account_role_object, (graphene::db::object),
(owner)(name)(metadata)(allowed_operations)(whitelisted_accounts)(valid_to))

View file

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

View file

@ -727,8 +727,8 @@ MAP_OBJECT_ID_TO_TYPE(graphene::chain::bet_object)
MAP_OBJECT_ID_TO_TYPE(graphene::chain::betting_market_position_object)
FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) )
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description) )
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id) )
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description)(event_id)(rules_id)(asset_id)(total_matched_bets_amount)(never_in_play)(delay_before_settling)(settling_time) )
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(description)(payout_condition)(resolution) )
FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(back_or_lay)(end_of_delay) )
FC_REFLECT_DERIVED( graphene::chain::betting_market_position_object, (graphene::db::object), (bettor_id)(betting_market_id)(pay_if_payout_condition)(pay_if_not_payout_condition)(pay_if_canceled)(pay_if_not_canceled)(fees_collected) )

View file

@ -27,6 +27,8 @@
#include <fc/filesystem.hpp>
#include <fc/filesystem.hpp>
namespace graphene { namespace chain {
struct index_entry;
using namespace graphene::protocol;

View file

@ -47,9 +47,11 @@ struct budget_record
// sinks of budget, should sum up to total_budget
share_type witness_budget = 0;
share_type worker_budget = 0;
share_type son_budget = 0;
// unused budget
share_type leftover_worker_funds = 0;
share_type leftover_son_funds = 0;
// change in supply due to budget operations
share_type supply_delta = 0;
@ -78,7 +80,9 @@ FC_REFLECT(graphene::chain::budget_record,
(total_budget)
(witness_budget)
(worker_budget)
(son_budget)
(leftover_worker_funds)
(leftover_son_funds)
(supply_delta)
)

View file

@ -31,6 +31,7 @@
#define GRAPHENE_MAX_NESTED_OBJECTS (200)
#define GRAPHENE_CURRENT_DB_VERSION "PPY2.5"
#define GRAPHENE_DEFAULT_MIN_SON_COUNT (5)
#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3

View file

@ -37,3 +37,4 @@ public:
} // namespace chain
} // namespace graphene

View file

@ -55,3 +55,4 @@ MAP_OBJECT_ID_TO_TYPE(graphene::chain::custom_account_authority_object)
FC_REFLECT_DERIVED( graphene::chain::custom_account_authority_object, (graphene::db::object),
(permission_id)(operation_type)(valid_from)(valid_to) )

View file

@ -38,3 +38,4 @@ public:
} // namespace chain
} // namespace graphene

View file

@ -52,3 +52,4 @@ MAP_OBJECT_ID_TO_TYPE(graphene::chain::custom_permission_object)
FC_REFLECT_DERIVED( graphene::chain::custom_permission_object, (graphene::db::object),
(account)(permission_name)(auth) )

View file

@ -34,6 +34,7 @@
#include <graphene/chain/genesis_state.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/betting_market_object.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/db/object_database.hpp>
#include <graphene/db/object.hpp>
@ -44,6 +45,8 @@
#include <graphene/protocol/protocol.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
#include <fc/log/logger.hpp>
#include <map>
@ -150,8 +153,8 @@ namespace graphene { namespace chain {
void add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts );
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
bool before_last_checkpoint()const;
void check_tansaction_for_duplicated_operations(const signed_transaction& trx);
void check_transaction_for_duplicated_operations(const signed_transaction& trx);
bool push_block( const signed_block& b, uint32_t skip = skip_nothing );
processed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
@ -252,6 +255,22 @@ namespace graphene { namespace chain {
*/
witness_id_type get_scheduled_witness(uint32_t slot_num)const;
/**
* @brief Get the son scheduled for block production in a slot.
*
* slot_num always corresponds to a time in the future.
*
* If slot_num == 1, returns the next scheduled son.
* If slot_num == 2, returns the next scheduled son after
* 1 block gap.
*
* Use the get_slot_time() and get_slot_at_time() functions
* to convert between slot_num and timestamp.
*
* Passing slot_num == 0 returns GRAPHENE_NULL_WITNESS
*/
son_id_type get_scheduled_son(uint32_t slot_num)const;
/**
* Get the time at which the given slot occurs.
*
@ -275,6 +294,8 @@ namespace graphene { namespace chain {
vector<witness_id_type> get_near_witness_schedule()const;
void update_witness_schedule();
void update_witness_schedule(const signed_block& next_block);
void update_son_schedule();
void update_son_schedule(const signed_block& next_block);
void check_lottery_end_by_participants( asset_id_type asset_id );
void check_ending_lotteries();
@ -295,6 +316,15 @@ namespace graphene { namespace chain {
uint64_t get_random_bits( uint64_t bound );
const witness_schedule_object& get_witness_schedule_object()const;
bool item_locked(const nft_id_type& item)const;
bool account_role_valid(const account_role_object& aro, account_id_type account, optional<int> op_type = optional<int>()) const;
std::set<son_id_type> get_sons_being_deregistered();
std::set<son_id_type> get_sons_being_reported_down();
std::set<son_id_type> get_sons_to_be_deregistered();
fc::optional<operation> create_son_deregister_proposal( son_id_type son_id, account_id_type paying_son );
signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op );
bool is_son_dereg_valid( son_id_type son_id );
bool is_son_active( son_id_type son_id );
bool is_asset_creation_allowed(const string& symbol);
time_point_sec head_block_time()const;
uint32_t head_block_num()const;
@ -543,9 +573,18 @@ namespace graphene { namespace chain {
void initialize_budget_record( fc::time_point_sec now, budget_record& rec )const;
void process_budget();
void pay_workers( share_type& budget );
void pay_sons();
void perform_son_tasks();
void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props);
void update_active_witnesses();
void update_active_committee_members();
void update_son_metrics( const vector<son_info>& curr_active_sons );
void update_active_sons();
void remove_son_proposal( const proposal_object& proposal );
void remove_inactive_son_down_proposals( const vector<son_id_type>& son_ids_to_remove );
void remove_inactive_son_proposals( const vector<son_id_type>& son_ids_to_remove );
void update_son_statuses( const vector<son_info>& cur_active_sons, const vector<son_info>& new_active_sons );
void update_son_wallet( const vector<son_info>& new_active_sons );
void update_worker_votes();
public:
@ -587,6 +626,7 @@ namespace graphene { namespace chain {
vector<uint64_t> _vote_tally_buffer;
vector<uint64_t> _witness_count_histogram_buffer;
vector<uint64_t> _committee_count_histogram_buffer;
vector<uint64_t> _son_count_histogram_buffer;
uint64_t _total_voting_stake;
flat_map<uint32_t,block_id_type> _checkpoints;

View file

@ -113,20 +113,20 @@
namespace graphene { namespace chain {
FC_DECLARE_EXCEPTION( chain_exception, 3000000 )
FC_DECLARE_DERIVED_EXCEPTION( database_query_exception, chain_exception, 3010000 )
FC_DECLARE_DERIVED_EXCEPTION( block_validate_exception, chain_exception, 3020000 )
FC_DECLARE_DERIVED_EXCEPTION( transaction_exception, chain_exception, 3030000 )
FC_DECLARE_DERIVED_EXCEPTION( operation_validate_exception, chain_exception, 3040000 )
FC_DECLARE_DERIVED_EXCEPTION( operation_evaluate_exception, chain_exception, 3050000 )
FC_DECLARE_DERIVED_EXCEPTION( utility_exception, chain_exception, 3060000 )
FC_DECLARE_DERIVED_EXCEPTION( undo_database_exception, chain_exception, 3070000 )
FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, chain_exception, 3080000 )
FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, chain_exception, 3090000 )
FC_DECLARE_DERIVED_EXCEPTION( plugin_exception, chain_exception, 3100000 )
FC_DECLARE_DERIVED_EXCEPTION( database_query_exception, chain_exception, 3010000 )
FC_DECLARE_DERIVED_EXCEPTION( block_validate_exception, chain_exception, 3020000 )
FC_DECLARE_DERIVED_EXCEPTION( operation_validate_exception, chain_exception, 3040000 )
FC_DECLARE_DERIVED_EXCEPTION( operation_evaluate_exception, chain_exception, 3050000 )
FC_DECLARE_DERIVED_EXCEPTION( utility_exception, chain_exception, 3060000 )
FC_DECLARE_DERIVED_EXCEPTION( undo_database_exception, chain_exception, 3070000 )
FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, chain_exception, 3080000 )
FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, chain_exception, 3090000 )
FC_DECLARE_DERIVED_EXCEPTION( plugin_exception, chain_exception, 3100000 )
FC_DECLARE_DERIVED_EXCEPTION( insufficient_feeds, chain_exception, 37006 )
FC_DECLARE_DERIVED_EXCEPTION( insufficient_feeds, chain_exception, 37006 )
FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001 )
FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001 )
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( transfer );
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( from_account_not_whitelisted, transfer, 1, "owner mismatch" )

View file

@ -25,8 +25,10 @@
#include <fc/uint128.hpp>
#include <graphene/protocol/chain_parameters.hpp>
#include <graphene/protocol/son_info.hpp>
#include <graphene/chain/types.hpp>
#include <graphene/db/object.hpp>
#include <graphene/chain/hardfork.hpp>
namespace graphene { namespace chain {
@ -50,6 +52,7 @@ namespace graphene { namespace chain {
uint32_t next_available_vote_id = 0;
vector<committee_member_id_type> active_committee_members; // updated once per maintenance interval
flat_set<witness_id_type> active_witnesses; // updated once per maintenance interval
vector<son_info> active_sons; // updated once per maintenance interval
// n.b. witness scheduling is done by witness_schedule object
};
@ -76,6 +79,9 @@ namespace graphene { namespace chain {
time_point_sec next_maintenance_time;
time_point_sec last_budget_time;
share_type witness_budget;
//Last SON Payout time, it can be different to the maintenance interval time
time_point_sec last_son_payout_time = HARDFORK_SON_TIME;
share_type son_budget = 0;
uint32_t accounts_registered_this_interval = 0;
/**
* Every time a block is missed this increases by
@ -133,6 +139,8 @@ FC_REFLECT_DERIVED( graphene::chain::dynamic_global_property_object, (graphene::
(next_maintenance_time)
(last_budget_time)
(witness_budget)
(last_son_payout_time)
(son_budget)
(accounts_registered_this_interval)
(recently_missed_count)
(current_aslot)
@ -147,6 +155,7 @@ FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::obje
(next_available_vote_id)
(active_committee_members)
(active_witnesses)
(active_sons)
)
GRAPHENE_EXTERNAL_SERIALIZATION( extern, graphene::chain::dynamic_global_property_object )

View file

@ -32,6 +32,7 @@ struct immutable_chain_parameters
{
uint16_t min_committee_member_count = GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT;
uint16_t min_witness_count = GRAPHENE_DEFAULT_MIN_WITNESS_COUNT;
uint16_t min_son_count = GRAPHENE_DEFAULT_MIN_SON_COUNT;
uint32_t num_special_accounts = 0;
uint32_t num_special_assets = 0;
};
@ -41,6 +42,7 @@ struct immutable_chain_parameters
FC_REFLECT( graphene::chain::immutable_chain_parameters,
(min_committee_member_count)
(min_witness_count)
(min_son_count)
(num_special_accounts)
(num_special_assets)
)

View file

@ -30,13 +30,12 @@
namespace graphene { namespace chain {
void operation_get_impacted_accounts(
const graphene::chain::operation& op,
fc::flat_set<graphene::chain::account_id_type>& result );
void operation_get_impacted_accounts( const graphene::chain::operation& op,
fc::flat_set<graphene::chain::account_id_type>& result,
bool ignore_custom_operation_required_auths );
void transaction_get_impacted_accounts(
const graphene::chain::transaction& tx,
fc::flat_set<graphene::chain::account_id_type>& result
);
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

View file

@ -1,6 +1,6 @@
#pragma once
#include <graphene/chain/types.hpp>
#include <graphene/protocol/types.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
@ -22,6 +22,7 @@ namespace graphene { namespace chain {
optional<uint16_t> revenue_split;
bool is_transferable = false;
bool is_sellable = true;
optional<account_role_id_type> account_role;
};
class nft_object : public abstract_object<nft_object>
@ -100,7 +101,8 @@ FC_REFLECT_DERIVED( graphene::chain::nft_metadata_object, (graphene::db::object)
(revenue_partner)
(revenue_split)
(is_transferable)
(is_sellable) )
(is_sellable)
(account_role) )
FC_REFLECT_DERIVED( graphene::chain::nft_object, (graphene::db::object),
(nft_metadata_id)

View file

@ -3,6 +3,7 @@
#include <graphene/protocol/operations.hpp>
namespace graphene
{
namespace chain

View file

@ -100,7 +100,7 @@ class account_transaction_history_object : public abstract_object<account_trans
uint32_t sequence = 0; /// the operation position within the given account
account_transaction_history_id_type next;
};
struct by_seq;
struct by_op;
struct by_opid;

View file

@ -30,6 +30,22 @@
namespace graphene { namespace chain {
class son_hardfork_visitor
{
public:
typedef void result_type;
database& db;
proposal_id_type prop_id;
son_hardfork_visitor( database& _db, const proposal_id_type& _prop_id ) : db( _db ), prop_id( _prop_id ) {}
template<typename T>
void operator()( const T &v ) const {}
void operator()( const son_deregister_operation &v );
void operator()( const son_report_down_operation &v );
};
class proposal_create_evaluator : public evaluator<proposal_create_evaluator>
{
public:

View file

@ -30,6 +30,9 @@
#include <boost/multi_index/composite_key.hpp>
namespace graphene { namespace chain {
using namespace graphene::protocol;
using namespace graphene::db;
class database;
/**

View file

@ -0,0 +1,599 @@
/*
* 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.
*/
#pragma once
#include <fc/container/flat_fwd.hpp>
#include <fc/io/varint.hpp>
#include <fc/io/enum_type.hpp>
#include <fc/crypto/sha224.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/optional.hpp>
#include <fc/safe.hpp>
#include <fc/container/flat.hpp>
#include <fc/string.hpp>
#include <fc/io/datastream.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/uint128.hpp>
#include <fc/static_variant.hpp>
#include <memory>
#include <vector>
#include <deque>
#include <cstdint>
#include <graphene/db/object_id.hpp>
#include <graphene/chain/protocol/config.hpp>
#define GRAPHENE_EXTERNAL_SERIALIZATION(ext, type) \
namespace fc { \
ext template void from_variant( const variant& v, type& vo, uint32_t max_depth ); \
ext template void to_variant( const type& v, variant& vo, uint32_t max_depth ); \
namespace raw { \
ext template void pack< datastream<size_t>, type >( datastream<size_t>& s, const type& tx, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); \
ext template void pack< datastream<char*>, type >( datastream<char*>& s, const type& tx, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); \
ext template void unpack< datastream<const char*>, type >( datastream<const char*>& s, type& tx, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); \
} } // fc::raw
#define FC_REFLECT_DERIVED_NO_TYPENAME( TYPE, INHERITS, MEMBERS ) \
namespace fc { \
template<> struct reflector<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
typedef fc::false_type is_enum; \
enum member_count_enum { \
local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\
total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\
}; \
FC_REFLECT_DERIVED_IMPL_INLINE( TYPE, INHERITS, MEMBERS ) \
}; \
} // fc
namespace graphene { namespace chain {
using namespace graphene::db;
using std::map;
using std::vector;
using std::unordered_map;
using std::string;
using std::deque;
using std::shared_ptr;
using std::weak_ptr;
using std::unique_ptr;
using std::set;
using std::pair;
using std::enable_shared_from_this;
using std::tie;
using std::make_pair;
using fc::smart_ref;
using fc::variant_object;
using fc::variant;
using fc::enum_type;
using fc::optional;
using fc::unsigned_int;
using fc::signed_int;
using fc::time_point_sec;
using fc::time_point;
using fc::safe;
using fc::flat_map;
using fc::flat_set;
using fc::static_variant;
using fc::ecc::range_proof_type;
using fc::ecc::range_proof_info;
using fc::ecc::commitment_type;
struct void_t{};
typedef fc::ecc::private_key private_key_type;
typedef fc::sha256 chain_id_type;
enum asset_issuer_permission_flags
{
charge_market_fee = 0x01, /**< an issuer-specified percentage of all market trades in this asset is paid to the issuer */
white_list = 0x02, /**< accounts must be whitelisted in order to hold this asset */
override_authority = 0x04, /**< issuer may transfer asset back to himself */
transfer_restricted = 0x08, /**< require the issuer to be one party to every transfer */
disable_force_settle = 0x10, /**< disable force settling */
global_settle = 0x20, /**< allow the bitasset issuer to force a global settling -- this may be set in permissions, but not flags */
disable_confidential = 0x40, /**< allow the asset to be used with confidential transactions */
witness_fed_asset = 0x80, /**< allow the asset to be fed by witnesses */
committee_fed_asset = 0x100 /**< allow the asset to be fed by the committee */
};
const static uint32_t ASSET_ISSUER_PERMISSION_MASK = charge_market_fee|white_list|override_authority|transfer_restricted|disable_force_settle|global_settle|disable_confidential
|witness_fed_asset|committee_fed_asset;
const static uint32_t UIA_ASSET_ISSUER_PERMISSION_MASK = charge_market_fee|white_list|override_authority|transfer_restricted|disable_confidential;
enum reserved_spaces
{
relative_protocol_ids = 0,
protocol_ids = 1,
implementation_ids = 2
};
inline bool is_relative( object_id_type o ){ return o.space() == 0; }
/**
* List all object types from all namespaces here so they can
* be easily reflected and displayed in debug output. If a 3rd party
* wants to extend the core code then they will have to change the
* packed_object::type field from enum_type to uint16 to avoid
* warnings when converting packed_objects to/from json.
*/
enum object_type
{
null_object_type,
base_object_type,
account_object_type,
asset_object_type,
force_settlement_object_type,
committee_member_object_type,
witness_object_type,
limit_order_object_type,
call_order_object_type,
custom_object_type,
proposal_object_type,
operation_history_object_type,
withdraw_permission_object_type,
vesting_balance_object_type,
worker_object_type,
balance_object_type,
tournament_object_type,
tournament_details_object_type,
match_object_type,
game_object_type,
sport_object_type,
event_group_object_type,
event_object_type,
betting_market_rules_object_type,
betting_market_group_object_type,
betting_market_object_type,
bet_object_type,
custom_permission_object_type,
custom_account_authority_object_type,
offer_object_type,
nft_metadata_type,
nft_object_type,
account_role_type,
son_object_type,
son_proposal_object_type,
son_wallet_object_type,
son_wallet_deposit_object_type,
son_wallet_withdraw_object_type,
sidechain_address_object_type,
sidechain_transaction_object_type,
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
};
enum impl_object_type
{
impl_global_property_object_type,
impl_dynamic_global_property_object_type,
impl_reserved0_object_type, // formerly index_meta_object_type, TODO: delete me
impl_asset_dynamic_data_type,
impl_asset_bitasset_data_type,
impl_account_balance_object_type,
impl_account_statistics_object_type,
impl_transaction_object_type,
impl_block_summary_object_type,
impl_account_transaction_history_object_type,
impl_blinded_balance_object_type,
impl_chain_property_object_type,
impl_witness_schedule_object_type,
impl_budget_record_object_type,
impl_special_authority_object_type,
impl_buyback_object_type,
impl_fba_accumulator_object_type,
impl_asset_dividend_data_type,
impl_pending_dividend_payout_balance_for_holder_object_type,
impl_distributed_dividend_balance_data_type,
impl_betting_market_position_object_type,
impl_global_betting_statistics_object_type,
impl_lottery_balance_object_type,
impl_sweeps_vesting_balance_object_type,
impl_offer_history_object_type,
impl_son_statistics_object_type,
impl_son_schedule_object_type
};
//typedef fc::unsigned_int object_id_type;
//typedef uint64_t object_id_type;
class account_object;
class committee_member_object;
class witness_object;
class asset_object;
class force_settlement_object;
class limit_order_object;
class call_order_object;
class custom_object;
class proposal_object;
class operation_history_object;
class withdraw_permission_object;
class vesting_balance_object;
class worker_object;
class balance_object;
class blinded_balance_object;
class tournament_object;
class tournament_details_object;
class match_object;
class game_object;
class sport_object;
class event_group_object;
class event_object;
class betting_market_rules_object;
class betting_market_group_object;
class betting_market_object;
class bet_object;
class custom_permission_object;
class custom_account_authority_object;
class offer_object;
class nft_metadata_object;
class nft_object;
class account_role_object;
class son_object;
class son_proposal_object;
class son_wallet_object;
class son_wallet_deposit_object;
class son_wallet_withdraw_object;
class sidechain_address_object;
class sidechain_transaction_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;
typedef object_id< protocol_ids, force_settlement_object_type, force_settlement_object> force_settlement_id_type;
typedef object_id< protocol_ids, committee_member_object_type, committee_member_object> committee_member_id_type;
typedef object_id< protocol_ids, witness_object_type, witness_object> witness_id_type;
typedef object_id< protocol_ids, limit_order_object_type, limit_order_object> limit_order_id_type;
typedef object_id< protocol_ids, call_order_object_type, call_order_object> call_order_id_type;
typedef object_id< protocol_ids, custom_object_type, custom_object> custom_id_type;
typedef object_id< protocol_ids, proposal_object_type, proposal_object> proposal_id_type;
typedef object_id< protocol_ids, operation_history_object_type, operation_history_object> operation_history_id_type;
typedef object_id< protocol_ids, withdraw_permission_object_type,withdraw_permission_object> withdraw_permission_id_type;
typedef object_id< protocol_ids, vesting_balance_object_type, vesting_balance_object> vesting_balance_id_type;
typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type;
typedef object_id< protocol_ids, balance_object_type, balance_object> balance_id_type;
typedef object_id< protocol_ids, tournament_object_type, tournament_object> tournament_id_type;
typedef object_id< protocol_ids, tournament_details_object_type, tournament_details_object> tournament_details_id_type;
typedef object_id< protocol_ids, match_object_type, match_object> match_id_type;
typedef object_id< protocol_ids, game_object_type, game_object> game_id_type;
typedef object_id< protocol_ids, sport_object_type, sport_object> sport_id_type;
typedef object_id< protocol_ids, event_group_object_type, event_group_object> event_group_id_type;
typedef object_id< protocol_ids, event_object_type, event_object> event_id_type;
typedef object_id< protocol_ids, betting_market_rules_object_type, betting_market_rules_object> betting_market_rules_id_type;
typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type;
typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type;
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
typedef object_id< protocol_ids, custom_permission_object_type, custom_permission_object> custom_permission_id_type;
typedef object_id< protocol_ids, custom_account_authority_object_type, custom_account_authority_object> custom_account_authority_id_type;
typedef object_id< protocol_ids, offer_object_type, offer_object> offer_id_type;
typedef object_id< protocol_ids, nft_metadata_type, nft_metadata_object> nft_metadata_id_type;
typedef object_id< protocol_ids, nft_object_type, nft_object> nft_id_type;
typedef object_id< protocol_ids, account_role_type, account_role_object> account_role_id_type;
typedef object_id< protocol_ids, son_object_type, son_object> son_id_type;
typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type;
typedef object_id< protocol_ids, son_wallet_object_type, son_wallet_object> son_wallet_id_type;
typedef object_id< protocol_ids, son_wallet_deposit_object_type, son_wallet_deposit_object> son_wallet_deposit_id_type;
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;
// implementation types
class global_property_object;
class dynamic_global_property_object;
class asset_dynamic_data_object;
class asset_bitasset_data_object;
class account_balance_object;
class account_statistics_object;
class transaction_object;
class block_summary_object;
class account_transaction_history_object;
class chain_property_object;
class witness_schedule_object;
class budget_record_object;
class special_authority_object;
class buyback_object;
class fba_accumulator_object;
class asset_dividend_data_object;
class pending_dividend_payout_balance_for_holder_object;
class betting_market_position_object;
class global_betting_statistics_object;
class lottery_balance_object;
class sweeps_vesting_balance_object;
class offer_history_object;
class son_statistics_object;
class son_schedule_object;
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
typedef object_id< implementation_ids, impl_asset_dynamic_data_type, asset_dynamic_data_object> asset_dynamic_data_id_type;
typedef object_id< implementation_ids, impl_asset_bitasset_data_type, asset_bitasset_data_object> asset_bitasset_data_id_type;
typedef object_id< implementation_ids, impl_asset_dividend_data_type, asset_dividend_data_object> asset_dividend_data_id_type;
typedef object_id< implementation_ids,
impl_pending_dividend_payout_balance_for_holder_object_type,
pending_dividend_payout_balance_for_holder_object> pending_dividend_payout_balance_for_holder_object_type;
typedef object_id< implementation_ids, impl_account_balance_object_type, account_balance_object> account_balance_id_type;
typedef object_id< implementation_ids, impl_account_statistics_object_type, account_statistics_object> account_statistics_id_type;
typedef object_id< implementation_ids, impl_transaction_object_type, transaction_object> transaction_obj_id_type;
typedef object_id< implementation_ids, impl_block_summary_object_type, block_summary_object> block_summary_id_type;
typedef object_id< implementation_ids,
impl_account_transaction_history_object_type,
account_transaction_history_object> account_transaction_history_id_type;
typedef object_id< implementation_ids, impl_chain_property_object_type, chain_property_object> chain_property_id_type;
typedef object_id< implementation_ids, impl_witness_schedule_object_type, witness_schedule_object> witness_schedule_id_type;
typedef object_id< implementation_ids, impl_budget_record_object_type, budget_record_object > budget_record_id_type;
typedef object_id< implementation_ids, impl_blinded_balance_object_type, blinded_balance_object > blinded_balance_id_type;
typedef object_id< implementation_ids, impl_special_authority_object_type, special_authority_object > special_authority_id_type;
typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type;
typedef object_id< implementation_ids, impl_fba_accumulator_object_type, fba_accumulator_object > fba_accumulator_id_type;
typedef object_id< implementation_ids, impl_betting_market_position_object_type, betting_market_position_object > betting_market_position_id_type;
typedef object_id< implementation_ids, impl_global_betting_statistics_object_type, global_betting_statistics_object > global_betting_statistics_id_type;
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_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;
typedef fc::array<char, GRAPHENE_MAX_ASSET_SYMBOL_LENGTH> symbol_type;
typedef fc::ripemd160 block_id_type;
typedef fc::ripemd160 checksum_type;
typedef fc::ripemd160 transaction_id_type;
typedef fc::sha256 digest_type;
typedef fc::ecc::compact_signature signature_type;
typedef safe<int64_t> share_type;
typedef fc::ripemd160 secret_hash_type;
typedef uint16_t weight_type;
struct public_key_type
{
struct binary_key
{
binary_key() {}
uint32_t check = 0;
fc::ecc::public_key_data data;
};
fc::ecc::public_key_data key_data;
public_key_type();
public_key_type( const fc::ecc::public_key_data& data );
public_key_type( const fc::ecc::public_key& pubkey );
explicit public_key_type( const std::string& base58str );
operator fc::ecc::public_key_data() const;
operator fc::ecc::public_key() const;
explicit operator std::string() const;
friend bool operator == ( const public_key_type& p1, const fc::ecc::public_key& p2);
friend bool operator == ( const public_key_type& p1, const public_key_type& p2);
friend bool operator != ( const public_key_type& p1, const public_key_type& p2);
// TODO: This is temporary for testing
bool is_valid_v1( const std::string& base58str );
bool is_valid_muse( const std::string& base58str );
};
struct extended_public_key_type
{
struct binary_key
{
binary_key() {}
uint32_t check = 0;
fc::ecc::extended_key_data data;
};
fc::ecc::extended_key_data key_data;
extended_public_key_type();
extended_public_key_type( const fc::ecc::extended_key_data& data );
extended_public_key_type( const fc::ecc::extended_public_key& extpubkey );
explicit extended_public_key_type( const std::string& base58str );
operator fc::ecc::extended_public_key() const;
explicit operator std::string() const;
friend bool operator == ( const extended_public_key_type& p1, const fc::ecc::extended_public_key& p2);
friend bool operator == ( const extended_public_key_type& p1, const extended_public_key_type& p2);
friend bool operator != ( const extended_public_key_type& p1, const extended_public_key_type& p2);
};
struct extended_private_key_type
{
struct binary_key
{
binary_key() {}
uint32_t check = 0;
fc::ecc::extended_key_data data;
};
fc::ecc::extended_key_data key_data;
extended_private_key_type();
extended_private_key_type( const fc::ecc::extended_key_data& data );
extended_private_key_type( const fc::ecc::extended_private_key& extprivkey );
explicit extended_private_key_type( const std::string& base58str );
operator fc::ecc::extended_private_key() const;
explicit operator std::string() const;
friend bool operator == ( const extended_private_key_type& p1, const fc::ecc::extended_private_key& p2);
friend bool operator == ( const extended_private_key_type& p1, const extended_private_key_type& p2);
friend bool operator != ( const extended_private_key_type& p1, const extended_private_key_type& p2);
};
typedef flat_map<std::string, std::string> internationalized_string_type;
typedef uint32_t bet_multiplier_type;
} } // graphene::chain
namespace fc
{
void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo, uint32_t max_depth = 2 );
void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo, uint32_t max_depth = 2 );
void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo, uint32_t max_depth = 2 );
void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo, uint32_t max_depth = 2 );
void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo, uint32_t max_depth = 2 );
void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo, uint32_t max_depth = 2 );
}
FC_REFLECT( graphene::chain::public_key_type, (key_data) )
FC_REFLECT( graphene::chain::public_key_type::binary_key, (data)(check) )
FC_REFLECT( graphene::chain::extended_public_key_type, (key_data) )
FC_REFLECT( graphene::chain::extended_public_key_type::binary_key, (check)(data) )
FC_REFLECT( graphene::chain::extended_private_key_type, (key_data) )
FC_REFLECT( graphene::chain::extended_private_key_type::binary_key, (check)(data) )
FC_REFLECT_ENUM( graphene::chain::object_type,
(null_object_type)
(base_object_type)
(account_object_type)
(force_settlement_object_type)
(asset_object_type)
(committee_member_object_type)
(witness_object_type)
(limit_order_object_type)
(call_order_object_type)
(custom_object_type)
(proposal_object_type)
(operation_history_object_type)
(withdraw_permission_object_type)
(vesting_balance_object_type)
(worker_object_type)
(balance_object_type)
(tournament_object_type)
(tournament_details_object_type)
(match_object_type)
(game_object_type)
(sport_object_type)
(event_group_object_type)
(event_object_type)
(betting_market_rules_object_type)
(betting_market_group_object_type)
(betting_market_object_type)
(bet_object_type)
(custom_permission_object_type)
(custom_account_authority_object_type)
(offer_object_type)
(nft_metadata_type)
(nft_object_type)
(account_role_type)
(son_object_type)
(son_proposal_object_type)
(son_wallet_object_type)
(son_wallet_deposit_object_type)
(son_wallet_withdraw_object_type)
(sidechain_address_object_type)
(sidechain_transaction_object_type)
(OBJECT_TYPE_COUNT)
)
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
(impl_global_property_object_type)
(impl_dynamic_global_property_object_type)
(impl_reserved0_object_type)
(impl_asset_dynamic_data_type)
(impl_asset_bitasset_data_type)
(impl_account_balance_object_type)
(impl_account_statistics_object_type)
(impl_transaction_object_type)
(impl_block_summary_object_type)
(impl_account_transaction_history_object_type)
(impl_blinded_balance_object_type)
(impl_chain_property_object_type)
(impl_witness_schedule_object_type)
(impl_budget_record_object_type)
(impl_special_authority_object_type)
(impl_buyback_object_type)
(impl_fba_accumulator_object_type)
(impl_asset_dividend_data_type)
(impl_pending_dividend_payout_balance_for_holder_object_type)
(impl_distributed_dividend_balance_data_type)
(impl_betting_market_position_object_type)
(impl_global_betting_statistics_object_type)
(impl_lottery_balance_object_type)
(impl_sweeps_vesting_balance_object_type)
(impl_offer_history_object_type)
(impl_son_statistics_object_type)
(impl_son_schedule_object_type)
)
FC_REFLECT_TYPENAME( graphene::chain::share_type )
FC_REFLECT_TYPENAME( graphene::chain::account_id_type )
FC_REFLECT_TYPENAME( graphene::chain::asset_id_type )
FC_REFLECT_TYPENAME( graphene::chain::force_settlement_id_type )
FC_REFLECT_TYPENAME( graphene::chain::committee_member_id_type )
FC_REFLECT_TYPENAME( graphene::chain::witness_id_type )
FC_REFLECT_TYPENAME( graphene::chain::limit_order_id_type )
FC_REFLECT_TYPENAME( graphene::chain::call_order_id_type )
FC_REFLECT_TYPENAME( graphene::chain::custom_id_type )
FC_REFLECT_TYPENAME( graphene::chain::proposal_id_type )
FC_REFLECT_TYPENAME( graphene::chain::operation_history_id_type )
FC_REFLECT_TYPENAME( graphene::chain::withdraw_permission_id_type )
FC_REFLECT_TYPENAME( graphene::chain::vesting_balance_id_type )
FC_REFLECT_TYPENAME( graphene::chain::worker_id_type )
FC_REFLECT_TYPENAME( graphene::chain::balance_id_type )
FC_REFLECT_TYPENAME( graphene::chain::sport_id_type )
FC_REFLECT_TYPENAME( graphene::chain::event_group_id_type )
FC_REFLECT_TYPENAME( graphene::chain::event_id_type )
FC_REFLECT_TYPENAME( graphene::chain::betting_market_rules_id_type )
FC_REFLECT_TYPENAME( graphene::chain::betting_market_group_id_type )
FC_REFLECT_TYPENAME( graphene::chain::betting_market_id_type )
FC_REFLECT_TYPENAME( graphene::chain::bet_id_type )
FC_REFLECT_TYPENAME( graphene::chain::tournament_id_type )
FC_REFLECT_TYPENAME( graphene::chain::offer_id_type )
FC_REFLECT_TYPENAME( graphene::chain::global_property_id_type )
FC_REFLECT_TYPENAME( graphene::chain::dynamic_global_property_id_type )
FC_REFLECT_TYPENAME( graphene::chain::asset_dynamic_data_id_type )
FC_REFLECT_TYPENAME( graphene::chain::asset_bitasset_data_id_type )
FC_REFLECT_TYPENAME( graphene::chain::account_balance_id_type )
FC_REFLECT_TYPENAME( graphene::chain::account_statistics_id_type )
FC_REFLECT_TYPENAME( graphene::chain::transaction_obj_id_type )
FC_REFLECT_TYPENAME( graphene::chain::block_summary_id_type )
FC_REFLECT_TYPENAME( graphene::chain::account_transaction_history_id_type )
FC_REFLECT_TYPENAME( graphene::chain::budget_record_id_type )
FC_REFLECT_TYPENAME( graphene::chain::special_authority_id_type )
FC_REFLECT_TYPENAME( graphene::chain::buyback_id_type )
FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type )
FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
FC_REFLECT_TYPENAME( graphene::chain::custom_permission_id_type )
FC_REFLECT_TYPENAME( graphene::chain::custom_account_authority_id_type )
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::son_id_type )
FC_REFLECT_TYPENAME( graphene::chain::son_proposal_id_type )
FC_REFLECT_TYPENAME( graphene::chain::son_wallet_id_type )
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( graphene::chain::void_t, )
FC_REFLECT_ENUM( graphene::chain::asset_issuer_permission_flags,
(charge_market_fee)
(white_list)
(transfer_restricted)
(override_authority)
(disable_force_settle)
(global_settle)
(disable_confidential)
(witness_fed_asset)
(committee_fed_asset)
)

View file

@ -0,0 +1,69 @@
#pragma once
#include <graphene/protocol/operations.hpp>
#include <graphene/chain/hardfork.hpp>
namespace graphene
{
namespace chain
{
struct rbac_operation_hardfork_visitor
{
typedef void result_type;
const fc::time_point_sec block_time;
rbac_operation_hardfork_visitor(const fc::time_point_sec bt) : block_time(bt) {}
void operator()(int op_type) const
{
int first_allowed_op = operation::tag<custom_permission_create_operation>::value;
switch (op_type)
{
case operation::tag<son_create_operation>::value:
case operation::tag<son_update_operation>::value:
case operation::tag<son_deregister_operation>::value:
case operation::tag<son_heartbeat_operation>::value:
case operation::tag<son_report_down_operation>::value:
case operation::tag<son_maintenance_operation>::value:
case operation::tag<son_wallet_recreate_operation>::value:
case operation::tag<son_wallet_update_operation>::value:
case operation::tag<son_wallet_deposit_create_operation>::value:
case operation::tag<son_wallet_deposit_process_operation>::value:
case operation::tag<son_wallet_withdraw_create_operation>::value:
case operation::tag<son_wallet_withdraw_process_operation>::value:
case operation::tag<sidechain_address_add_operation>::value:
case operation::tag<sidechain_address_update_operation>::value:
case operation::tag<sidechain_address_delete_operation>::value:
case operation::tag<sidechain_transaction_create_operation>::value:
case operation::tag<sidechain_transaction_sign_operation>::value:
case operation::tag<sidechain_transaction_send_operation>::value:
case operation::tag<sidechain_transaction_settle_operation>::value:
FC_ASSERT(block_time >= HARDFORK_SON_TIME, "Custom permissions and roles not allowed on this operation yet!");
break;
case operation::tag<custom_permission_create_operation>::value:
case operation::tag<custom_permission_update_operation>::value:
case operation::tag<custom_permission_delete_operation>::value:
case operation::tag<custom_account_authority_create_operation>::value:
case operation::tag<custom_account_authority_update_operation>::value:
case operation::tag<custom_account_authority_delete_operation>::value:
case operation::tag<offer_operation>::value:
case operation::tag<bid_operation>::value:
case operation::tag<cancel_offer_operation>::value:
case operation::tag<finalize_offer_operation>::value:
case operation::tag<nft_metadata_create_operation>::value:
case operation::tag<nft_metadata_update_operation>::value:
case operation::tag<nft_mint_operation>::value:
case operation::tag<nft_safe_transfer_from_operation>::value:
case operation::tag<nft_approve_operation>::value:
case operation::tag<nft_set_approval_for_all_operation>::value:
case operation::tag<account_role_create_operation>::value:
case operation::tag<account_role_update_operation>::value:
case operation::tag<account_role_delete_operation>::value:
FC_ASSERT(block_time >= HARDFORK_NFT_TIME, "Custom permissions and roles not allowed on this operation yet!");
break;
default:
FC_ASSERT(op_type >= operation::tag<transfer_operation>::value && op_type < first_allowed_op, "Custom permissions and roles not allowed on this operation!");
}
}
};
} // namespace chain
} // namespace graphene

View file

@ -0,0 +1,34 @@
#pragma once
#include <graphene/chain/evaluator.hpp>
#include <graphene/protocol/sidechain_address.hpp>
namespace graphene { namespace chain {
class add_sidechain_address_evaluator : public evaluator<add_sidechain_address_evaluator>
{
public:
typedef sidechain_address_add_operation operation_type;
void_result do_evaluate(const sidechain_address_add_operation& o);
object_id_type do_apply(const sidechain_address_add_operation& o);
};
class update_sidechain_address_evaluator : public evaluator<update_sidechain_address_evaluator>
{
public:
typedef sidechain_address_update_operation operation_type;
void_result do_evaluate(const sidechain_address_update_operation& o);
object_id_type do_apply(const sidechain_address_update_operation& o);
};
class delete_sidechain_address_evaluator : public evaluator<delete_sidechain_address_evaluator>
{
public:
typedef sidechain_address_delete_operation operation_type;
void_result do_evaluate(const sidechain_address_delete_operation& o);
void_result do_apply(const sidechain_address_delete_operation& o);
};
} } // namespace graphene::chain

View file

@ -0,0 +1,95 @@
#pragma once
#include <graphene/protocol/types.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
#include <boost/multi_index/composite_key.hpp>
namespace graphene { namespace chain {
using namespace graphene::db;
using namespace graphene::protocol;
/**
* @class sidechain_address_object
* @brief tracks information about a sidechain addresses for user accounts.
* @ingroup object
*/
class sidechain_address_object : public abstract_object<sidechain_address_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = sidechain_address_object_type;
account_id_type sidechain_address_account;
sidechain_type sidechain;
string deposit_public_key;
string deposit_address;
string deposit_address_data;
string withdraw_public_key;
string withdraw_address;
time_point_sec valid_from;
time_point_sec expires;
sidechain_address_object() :
sidechain(sidechain_type::bitcoin),
deposit_public_key(""),
deposit_address(""),
withdraw_public_key(""),
withdraw_address("") {}
};
struct by_account;
struct by_sidechain;
struct by_sidechain_and_deposit_public_key_and_expires;
struct by_withdraw_public_key;
struct by_account_and_sidechain_and_expires;
struct by_sidechain_and_deposit_address_and_expires;
using sidechain_address_multi_index_type = multi_index_container<
sidechain_address_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_non_unique< tag<by_account>,
member<sidechain_address_object, account_id_type, &sidechain_address_object::sidechain_address_account>
>,
ordered_non_unique< tag<by_sidechain>,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>
>,
ordered_unique< tag<by_sidechain_and_deposit_public_key_and_expires>,
composite_key<sidechain_address_object,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>,
member<sidechain_address_object, string, &sidechain_address_object::deposit_public_key>,
member<sidechain_address_object, time_point_sec, &sidechain_address_object::expires>
>
>,
ordered_non_unique< tag<by_withdraw_public_key>,
member<sidechain_address_object, string, &sidechain_address_object::withdraw_public_key>
>,
ordered_non_unique< tag<by_account_and_sidechain_and_expires>,
composite_key<sidechain_address_object,
member<sidechain_address_object, account_id_type, &sidechain_address_object::sidechain_address_account>,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>,
member<sidechain_address_object, time_point_sec, &sidechain_address_object::expires>
>
>,
ordered_non_unique< tag<by_sidechain_and_deposit_address_and_expires>,
composite_key<sidechain_address_object,
member<sidechain_address_object, sidechain_type, &sidechain_address_object::sidechain>,
member<sidechain_address_object, string, &sidechain_address_object::deposit_address>,
member<sidechain_address_object, time_point_sec, &sidechain_address_object::expires>
>
>
>
>;
using sidechain_address_index = generic_index<sidechain_address_object, sidechain_address_multi_index_type>;
} } // graphene::chain
MAP_OBJECT_ID_TO_TYPE(graphene::chain::sidechain_address_object)
FC_REFLECT_DERIVED( graphene::chain::sidechain_address_object, (graphene::db::object),
(sidechain_address_account) (sidechain)
(deposit_public_key) (deposit_address) (deposit_address_data)
(withdraw_public_key) (withdraw_address) (valid_from) (expires) )

View file

@ -0,0 +1,22 @@
#pragma once
#include <fc/reflect/reflect.hpp>
namespace graphene { namespace chain {
enum class sidechain_type {
unknown,
bitcoin,
ethereum,
eos,
peerplays
};
} }
FC_REFLECT_ENUM(graphene::chain::sidechain_type,
(unknown)
(bitcoin)
(ethereum)
(eos)
(peerplays) )

View file

@ -0,0 +1,43 @@
#pragma once
#include <graphene/chain/evaluator.hpp>
#include <graphene/protocol/sidechain_transaction.hpp>
namespace graphene { namespace chain {
class sidechain_transaction_create_evaluator : public evaluator<sidechain_transaction_create_evaluator>
{
public:
typedef sidechain_transaction_create_operation operation_type;
void_result do_evaluate(const sidechain_transaction_create_operation& o);
object_id_type do_apply(const sidechain_transaction_create_operation& o);
};
class sidechain_transaction_sign_evaluator : public evaluator<sidechain_transaction_sign_evaluator>
{
public:
typedef sidechain_transaction_sign_operation operation_type;
void_result do_evaluate(const sidechain_transaction_sign_operation& o);
object_id_type do_apply(const sidechain_transaction_sign_operation& o);
};
class sidechain_transaction_send_evaluator : public evaluator<sidechain_transaction_send_evaluator>
{
public:
typedef sidechain_transaction_send_operation operation_type;
void_result do_evaluate(const sidechain_transaction_send_operation& o);
object_id_type do_apply(const sidechain_transaction_send_operation& o);
};
class sidechain_transaction_settle_evaluator : public evaluator<sidechain_transaction_settle_evaluator>
{
public:
typedef sidechain_transaction_settle_operation operation_type;
void_result do_evaluate(const sidechain_transaction_settle_operation& o);
object_id_type do_apply(const sidechain_transaction_settle_operation& o);
};
} } // namespace graphene::chain

View file

@ -0,0 +1,83 @@
#pragma once
#include <boost/multi_index/composite_key.hpp>
#include <graphene/protocol/types.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
#include <graphene/protocol/son_info.hpp>
namespace graphene { namespace chain {
using namespace graphene::db;
using namespace graphene::protocol;
enum class sidechain_transaction_status {
invalid,
valid,
complete,
sent,
settled
};
/**
* @class sidechain_transaction_object
* @brief tracks state of sidechain transaction during signing process.
* @ingroup object
*/
class sidechain_transaction_object : public abstract_object<sidechain_transaction_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = sidechain_transaction_object_type;
sidechain_type sidechain;
object_id_type object_id;
std::string transaction;
std::vector<son_info> signers;
std::vector<std::pair<son_id_type, std::string>> signatures;
std::string sidechain_transaction;
uint32_t total_weight = 0;
uint32_t current_weight = 0;
uint32_t threshold = 0;
sidechain_transaction_status status;
};
struct by_object_id;
struct by_sidechain_and_status;
using sidechain_transaction_multi_index_type = multi_index_container<
sidechain_transaction_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_unique< tag<by_object_id>,
member<sidechain_transaction_object, object_id_type, &sidechain_transaction_object::object_id>
>,
ordered_non_unique< tag<by_sidechain_and_status>,
composite_key<sidechain_transaction_object,
member<sidechain_transaction_object, sidechain_type, &sidechain_transaction_object::sidechain>,
member<sidechain_transaction_object, sidechain_transaction_status, &sidechain_transaction_object::status>
>
>
>
>;
using sidechain_transaction_index = generic_index<sidechain_transaction_object, sidechain_transaction_multi_index_type>;
} } // graphene::chain
FC_REFLECT_ENUM( graphene::chain::sidechain_transaction_status,
(invalid)
(valid)
(complete)
(sent)
(settled) )
FC_REFLECT_DERIVED( graphene::chain::sidechain_transaction_object, (graphene::db::object ),
(sidechain)
(object_id)
(transaction)
(signers)
(signatures)
(sidechain_transaction)
(total_weight)
(current_weight)
(threshold)
(status) )

View file

@ -0,0 +1,61 @@
#pragma once
#include <graphene/chain/evaluator.hpp>
#include <graphene/protocol/son.hpp>
namespace graphene { namespace chain {
class create_son_evaluator : public evaluator<create_son_evaluator>
{
public:
typedef son_create_operation operation_type;
void_result do_evaluate(const son_create_operation& o);
object_id_type do_apply(const son_create_operation& o);
};
class update_son_evaluator : public evaluator<update_son_evaluator>
{
public:
typedef son_update_operation operation_type;
void_result do_evaluate(const son_update_operation& o);
object_id_type do_apply(const son_update_operation& o);
};
class deregister_son_evaluator : public evaluator<deregister_son_evaluator>
{
public:
typedef son_deregister_operation operation_type;
void_result do_evaluate(const son_deregister_operation& o);
void_result do_apply(const son_deregister_operation& o);
};
class son_heartbeat_evaluator : public evaluator<son_heartbeat_evaluator>
{
public:
typedef son_heartbeat_operation operation_type;
void_result do_evaluate(const son_heartbeat_operation& o);
object_id_type do_apply(const son_heartbeat_operation& o);
};
class son_report_down_evaluator : public evaluator<son_report_down_evaluator>
{
public:
typedef son_report_down_operation operation_type;
void_result do_evaluate(const son_report_down_operation& o);
object_id_type do_apply(const son_report_down_operation& o);
};
class son_maintenance_evaluator : public evaluator<son_maintenance_evaluator>
{
public:
typedef son_maintenance_operation operation_type;
void_result do_evaluate(const son_maintenance_operation& o);
object_id_type do_apply(const son_maintenance_operation& o);
};
} } // namespace graphene::chain

View file

@ -0,0 +1,47 @@
#pragma once
#include <graphene/chain/protocol/types.hpp>
#include <graphene/chain/sidechain_defs.hpp>
namespace graphene { namespace chain {
using namespace graphene::db;
/**
* @class son_info
* @brief tracks information about a SON info required to re/create primary wallet
* @ingroup object
*/
struct son_info {
son_id_type son_id;
weight_type weight = 0;
public_key_type signing_key;
flat_map<sidechain_type, string> sidechain_public_keys;
bool operator==(const son_info& rhs) {
bool son_sets_equal =
(son_id == rhs.son_id) &&
(weight == rhs.weight) &&
(signing_key == rhs.signing_key) &&
(sidechain_public_keys.size() == rhs.sidechain_public_keys.size());
if (son_sets_equal) {
bool sidechain_public_keys_equal = true;
for (size_t i = 0; i < sidechain_public_keys.size(); i++) {
const auto lhs_scpk = sidechain_public_keys.nth(i);
const auto rhs_scpk = rhs.sidechain_public_keys.nth(i);
sidechain_public_keys_equal = sidechain_public_keys_equal &&
(lhs_scpk->first == rhs_scpk->first) &&
(lhs_scpk->second == rhs_scpk->second);
}
son_sets_equal = son_sets_equal && sidechain_public_keys_equal;
}
return son_sets_equal;
}
};
} }
FC_REFLECT( graphene::chain::son_info,
(son_id)
(weight)
(signing_key)
(sidechain_public_keys) )

View file

@ -0,0 +1,149 @@
#pragma once
#include <graphene/protocol/types.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
namespace graphene { namespace chain {
using namespace graphene::db;
enum class son_status
{
inactive,
active,
request_maintenance,
in_maintenance,
deregistered
};
/**
* @class son_statistics_object
* @ingroup object
* @ingroup implementation
*
* This object contains regularly updated statistical data about an SON. It is provided for the purpose of
* separating the SON transaction data that changes frequently from the SON object data that is mostly static.
*/
class son_statistics_object : public graphene::db::abstract_object<son_statistics_object>
{
public:
static const uint8_t space_id = implementation_ids;
static const uint8_t type_id = impl_son_statistics_object_type;
son_id_type owner;
// Lifetime total transactions signed
uint64_t total_txs_signed = 0;
// Transactions signed since the last son payouts
uint64_t txs_signed = 0;
// Total Voted Active time i.e. duration selected as part of voted active SONs
uint64_t total_voted_time = 0;
// Total Downtime barring the current down time in seconds, used for stats to present to user
uint64_t total_downtime = 0;
// Current Interval Downtime since last maintenance
uint64_t current_interval_downtime = 0;
// Down timestamp, if son status is in_maintenance use this
fc::time_point_sec last_down_timestamp;
// Last Active heartbeat timestamp
fc::time_point_sec last_active_timestamp;
// Deregistered Timestamp
fc::time_point_sec deregistered_timestamp;
// Total sidechain transactions reported by SON network while SON was active
uint64_t total_sidechain_txs_reported = 0;
// Sidechain transactions reported by this SON
uint64_t sidechain_txs_reported = 0;
};
/**
* @class son_object
* @brief tracks information about a SON account.
* @ingroup object
*/
class son_object : public abstract_object<son_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_object_type;
account_id_type son_account;
vote_id_type vote_id;
uint64_t total_votes = 0;
string url;
vesting_balance_id_type deposit;
public_key_type signing_key;
vesting_balance_id_type pay_vb;
son_statistics_id_type statistics;
son_status status = son_status::inactive;
flat_map<sidechain_type, string> sidechain_public_keys;
void pay_son_fee(share_type pay, database& db);
bool has_valid_config()const;
};
struct by_account;
struct by_vote_id;
using son_multi_index_type = multi_index_container<
son_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_unique< tag<by_account>,
member<son_object, account_id_type, &son_object::son_account>
>,
ordered_unique< tag<by_vote_id>,
member<son_object, vote_id_type, &son_object::vote_id>
>
>
>;
using son_index = generic_index<son_object, son_multi_index_type>;
struct by_owner;
using son_stats_multi_index_type = multi_index_container<
son_statistics_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_unique< tag<by_owner>,
member<son_statistics_object, son_id_type, &son_statistics_object::owner>
>
>
>;
using son_stats_index = generic_index<son_statistics_object, son_stats_multi_index_type>;
} } // graphene::chain
MAP_OBJECT_ID_TO_TYPE(graphene::chain::son_statistics_object)
MAP_OBJECT_ID_TO_TYPE(graphene::chain::son_object)
FC_REFLECT_ENUM(graphene::chain::son_status, (inactive)(active)(request_maintenance)(in_maintenance)(deregistered) )
FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object),
(son_account)
(vote_id)
(total_votes)
(url)
(deposit)
(signing_key)
(pay_vb)
(statistics)
(status)
(sidechain_public_keys)
)
FC_REFLECT_DERIVED( graphene::chain::son_statistics_object,
(graphene::db::object),
(owner)
(total_txs_signed)
(txs_signed)
(total_voted_time)
(total_downtime)
(current_interval_downtime)
(last_down_timestamp)
(last_active_timestamp)
(deregistered_timestamp)
(total_sidechain_txs_reported)
(sidechain_txs_reported)
)
GRAPHENE_EXTERNAL_SERIALIZATION( extern, graphene::chain::son_object )
GRAPHENE_EXTERNAL_SERIALIZATION( extern, graphene::chain::son_statistics_object )

View file

@ -0,0 +1,42 @@
#pragma once
#include <graphene/protocol/types.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
namespace graphene { namespace chain {
enum class son_proposal_type
{
son_deregister_proposal,
son_report_down_proposal
};
class son_proposal_object : public abstract_object<son_proposal_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_proposal_object_type;
son_proposal_id_type get_id()const { return id; }
proposal_id_type proposal_id;
son_id_type son_id;
son_proposal_type proposal_type;
};
struct by_proposal;
using son_proposal_multi_index_container = multi_index_container<
son_proposal_object,
indexed_by<
ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >,
ordered_unique< tag< by_proposal >, member< son_proposal_object, proposal_id_type, &son_proposal_object::proposal_id > >
>
>;
using son_proposal_index = generic_index<son_proposal_object, son_proposal_multi_index_container>;
} } // graphene::chain
FC_REFLECT_ENUM( graphene::chain::son_proposal_type, (son_deregister_proposal)(son_report_down_proposal) )
FC_REFLECT_DERIVED( graphene::chain::son_proposal_object, (graphene::chain::object), (proposal_id)(son_id)(proposal_type) )

View file

@ -0,0 +1,24 @@
#pragma once
#include <graphene/chain/evaluator.hpp>
namespace graphene { namespace chain {
class create_son_wallet_deposit_evaluator : public evaluator<create_son_wallet_deposit_evaluator>
{
public:
typedef son_wallet_deposit_create_operation operation_type;
void_result do_evaluate(const son_wallet_deposit_create_operation& o);
object_id_type do_apply(const son_wallet_deposit_create_operation& o);
};
class process_son_wallet_deposit_evaluator : public evaluator<process_son_wallet_deposit_evaluator>
{
public:
typedef son_wallet_deposit_process_operation operation_type;
void_result do_evaluate(const son_wallet_deposit_process_operation& o);
object_id_type do_apply(const son_wallet_deposit_process_operation& o);
};
} } // namespace graphene::chain

View file

@ -0,0 +1,72 @@
#pragma once
#include <graphene/protocol/asset.hpp>
#include <graphene/protocol/types.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
namespace graphene { namespace chain {
using namespace graphene::db;
using namespace graphene::protocol;
/**
* @class son_wallet_deposit_object
* @brief tracks information about a SON wallet deposit.
* @ingroup object
*/
class son_wallet_deposit_object : public abstract_object<son_wallet_deposit_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_wallet_deposit_object_type;
time_point_sec timestamp;
uint32_t block_num;
sidechain_type sidechain = sidechain_type::unknown;
std::string sidechain_uid;
std::string sidechain_transaction_id;
std::string sidechain_from;
std::string sidechain_to;
std::string sidechain_currency;
safe<int64_t> sidechain_amount;
chain::account_id_type peerplays_from;
chain::account_id_type peerplays_to;
chain::asset peerplays_asset;
std::map<son_id_type, weight_type> expected_reports;
std::set<son_id_type> received_reports;
bool confirmed = false;
bool processed = false;
};
struct by_sidechain_uid;
struct by_sidechain_and_confirmed_and_processed;
using son_wallet_deposit_multi_index_type = multi_index_container<
son_wallet_deposit_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_unique< tag<by_sidechain_uid>,
member<son_wallet_deposit_object, std::string, &son_wallet_deposit_object::sidechain_uid>
>,
ordered_non_unique< tag<by_sidechain_and_confirmed_and_processed>,
composite_key<son_wallet_deposit_object,
member<son_wallet_deposit_object, sidechain_type, &son_wallet_deposit_object::sidechain>,
member<son_wallet_deposit_object, bool, &son_wallet_deposit_object::confirmed>,
member<son_wallet_deposit_object, bool, &son_wallet_deposit_object::processed>
>
>
>
>;
using son_wallet_deposit_index = generic_index<son_wallet_deposit_object, son_wallet_deposit_multi_index_type>;
} } // graphene::chain
MAP_OBJECT_ID_TO_TYPE(graphene::chain::son_wallet_deposit_object)
FC_REFLECT_DERIVED( graphene::chain::son_wallet_deposit_object, (graphene::db::object),
(timestamp) (block_num) (sidechain)
(sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_currency) (sidechain_amount)
(peerplays_from) (peerplays_to) (peerplays_asset)
(expected_reports) (received_reports)
(confirmed) (processed) )

View file

@ -0,0 +1,25 @@
#pragma once
#include <graphene/chain/evaluator.hpp>
#include <graphene/protocol/son_wallet.hpp>
namespace graphene { namespace chain {
class recreate_son_wallet_evaluator : public evaluator<recreate_son_wallet_evaluator>
{
public:
typedef son_wallet_recreate_operation operation_type;
void_result do_evaluate(const son_wallet_recreate_operation& o);
object_id_type do_apply(const son_wallet_recreate_operation& o);
};
class update_son_wallet_evaluator : public evaluator<update_son_wallet_evaluator>
{
public:
typedef son_wallet_update_operation operation_type;
void_result do_evaluate(const son_wallet_update_operation& o);
object_id_type do_apply(const son_wallet_update_operation& o);
};
} } // namespace graphene::chain

View file

@ -0,0 +1,54 @@
#pragma once
#include <graphene/protocol/types.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
#include <graphene/protocol/son_info.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
#include <boost/multi_index_container.hpp>
namespace graphene { namespace chain {
using namespace graphene::protocol;
using namespace graphene::db;
using namespace boost::multi_index;
/**
* @class son_wallet_object
* @brief tracks information about a SON wallet.
* @ingroup object
*/
class son_wallet_object : public abstract_object<son_wallet_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_wallet_object_type;
time_point_sec valid_from;
time_point_sec expires;
flat_map<sidechain_type, string> addresses;
vector<son_info> sons;
};
struct by_valid_from;
struct by_expires;
using son_wallet_multi_index_type = multi_index_container<
son_wallet_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_unique< tag<by_valid_from>,
member<son_wallet_object, time_point_sec, &son_wallet_object::valid_from>
>,
ordered_unique< tag<by_expires>,
member<son_wallet_object, time_point_sec, &son_wallet_object::expires>
>
>
>;
using son_wallet_index = generic_index<son_wallet_object, son_wallet_multi_index_type>;
} } // graphene::chain
FC_REFLECT_DERIVED( graphene::chain::son_wallet_object, (graphene::db::object),
(valid_from) (expires) (addresses) (sons) )

View file

@ -0,0 +1,24 @@
#pragma once
#include <graphene/chain/evaluator.hpp>
namespace graphene { namespace chain {
class create_son_wallet_withdraw_evaluator : public evaluator<create_son_wallet_withdraw_evaluator>
{
public:
typedef son_wallet_withdraw_create_operation operation_type;
void_result do_evaluate(const son_wallet_withdraw_create_operation& o);
object_id_type do_apply(const son_wallet_withdraw_create_operation& o);
};
class process_son_wallet_withdraw_evaluator : public evaluator<process_son_wallet_withdraw_evaluator>
{
public:
typedef son_wallet_withdraw_process_operation operation_type;
void_result do_evaluate(const son_wallet_withdraw_process_operation& o);
object_id_type do_apply(const son_wallet_withdraw_process_operation& o);
};
} } // namespace graphene::chain

View file

@ -0,0 +1,71 @@
#pragma once
#include <graphene/protocol/asset.hpp>
#include <graphene/protocol/types.hpp>
#include <graphene/protocol/sidechain_defs.hpp>
namespace graphene { namespace chain {
using namespace graphene::db;
using namespace graphene::protocol;
/**
* @class son_wallet_withdraw_object
* @brief tracks information about a SON wallet withdrawal.
* @ingroup object
*/
class son_wallet_withdraw_object : public abstract_object<son_wallet_withdraw_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_wallet_withdraw_object_type;
time_point_sec timestamp;
uint32_t block_num;
sidechain_type sidechain = sidechain_type::unknown;
std::string peerplays_uid;
std::string peerplays_transaction_id;
chain::account_id_type peerplays_from;
chain::asset peerplays_asset;
sidechain_type withdraw_sidechain;
std::string withdraw_address;
std::string withdraw_currency;
safe<int64_t> withdraw_amount;
std::map<son_id_type, weight_type> expected_reports;
std::set<son_id_type> received_reports;
bool confirmed = false;
bool processed = false;
};
struct by_peerplays_uid;
struct by_withdraw_sidechain_and_confirmed_and_processed;
using son_wallet_withdraw_multi_index_type = multi_index_container<
son_wallet_withdraw_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_unique< tag<by_peerplays_uid>,
member<son_wallet_withdraw_object, std::string, &son_wallet_withdraw_object::peerplays_uid>
>,
ordered_non_unique< tag<by_withdraw_sidechain_and_confirmed_and_processed>,
composite_key<son_wallet_withdraw_object,
member<son_wallet_withdraw_object, sidechain_type, &son_wallet_withdraw_object::withdraw_sidechain>,
member<son_wallet_withdraw_object, bool, &son_wallet_withdraw_object::confirmed>,
member<son_wallet_withdraw_object, bool, &son_wallet_withdraw_object::processed>
>
>
>
>;
using son_wallet_withdraw_index = generic_index<son_wallet_withdraw_object, son_wallet_withdraw_multi_index_type>;
} } // graphene::chain
MAP_OBJECT_ID_TO_TYPE(graphene::chain::son_wallet_withdraw_object)
FC_REFLECT_DERIVED( graphene::chain::son_wallet_withdraw_object, (graphene::db::object),
(timestamp) (block_num) (sidechain)
(peerplays_uid) (peerplays_transaction_id) (peerplays_from) (peerplays_asset)
(withdraw_sidechain) (withdraw_address) (withdraw_currency) (withdraw_amount)
(expected_reports) (received_reports)
(confirmed) (processed) )

View file

@ -29,6 +29,7 @@ namespace protocol { struct signed_transaction; }
namespace chain {
class database;
using protocol::signed_transaction;
using protocol::operation_result;
/**
* Place holder for state tracked while processing a transaction. This class provides helper methods that are
@ -42,7 +43,7 @@ namespace chain {
database& db()const { assert( _db ); return *_db; }
vector<operation_result> operation_results;
std::vector<operation_result> operation_results;
const signed_transaction* _trx = nullptr;
database* _db = nullptr;

View file

@ -78,3 +78,4 @@ MAP_OBJECT_ID_TO_TYPE(graphene::chain::transaction_history_object)
FC_REFLECT_DERIVED( graphene::chain::transaction_history_object, (graphene::db::object), (trx)(trx_id) )
GRAPHENE_EXTERNAL_SERIALIZATION( extern, graphene::chain::transaction_history_object )

View file

@ -52,4 +52,6 @@ GRAPHENE_DEFINE_IDS(chain, implementation_ids, impl_,
(global_betting_statistics)
(lottery_balance)
(sweeps_vesting_balance)
(offer_history))
(offer_history)
(son_statistics)
(son_schedule))

View file

@ -26,6 +26,7 @@
#include <graphene/protocol/vesting.hpp>
#include <graphene/protocol/asset.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
@ -119,10 +120,32 @@ namespace graphene { namespace chain {
void on_withdraw(const vesting_policy_context& ctx);
};
/**
* @brief Cant withdraw anything while balance is in this policy.
*
* This policy is needed to register SON users where balance may be claimable only after
* the SON object is deleted(plus a linear policy).
* When deleting a SON member the dormant mode will be replaced by a linear policy.
*
* @note New funds may not be added to a dormant vesting balance.
*/
struct dormant_vesting_policy
{
asset get_allowed_withdraw(const vesting_policy_context& ctx)const;
bool is_deposit_allowed(const vesting_policy_context& ctx)const;
bool is_deposit_vested_allowed(const vesting_policy_context&)const { return false; }
bool is_withdraw_allowed(const vesting_policy_context& ctx)const;
void on_deposit(const vesting_policy_context& ctx);
void on_deposit_vested(const vesting_policy_context&)
{ FC_THROW( "May not deposit vested into a linear vesting balance." ); }
void on_withdraw(const vesting_policy_context& ctx);
};
typedef fc::static_variant<
linear_vesting_policy,
cdd_vesting_policy
> vesting_policy;
cdd_vesting_policy,
dormant_vesting_policy
> vesting_policy;
/**
* Vesting balance object is a balance that is locked by the blockchain for a period of time.
@ -141,7 +164,7 @@ namespace graphene { namespace chain {
/// The vesting policy stores details on when funds vest, and controls when they may be withdrawn
vesting_policy policy;
/// We can have 2 types of vesting, gpos and all the rest
/// We can have 3 types of vesting, gpos, son and the rest
vesting_balance_type balance_type = vesting_balance_type::normal;
vesting_balance_object() {}
@ -227,6 +250,8 @@ FC_REFLECT(graphene::chain::cdd_vesting_policy,
(coin_seconds_earned_last_update)
)
FC_REFLECT(graphene::chain::dormant_vesting_policy, )
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy )
FC_REFLECT_DERIVED(graphene::chain::vesting_balance_object, (graphene::db::object),

View file

@ -63,6 +63,17 @@ struct vote_counter
out_auth = auth;
}
void finish_2_3( authority& out_auth )
{
if( total_votes == 0 )
return;
assert( total_votes <= std::numeric_limits<uint32_t>::max() );
uint32_t weight = uint32_t( total_votes );
weight = (weight * 2 / 3) + 1;
auth.weight_threshold = weight;
out_auth = auth;
}
bool is_empty()const
{
return (total_votes == 0);

View file

@ -56,6 +56,22 @@ typedef generic_far_future_witness_scheduler<
/* debug = */ true
> far_future_witness_scheduler;
typedef generic_witness_scheduler<
/* WitnessID = */ son_id_type,
/* RNG = */ witness_scheduler_rng,
/* CountType = */ decltype( chain_parameters::extensions.value.maximum_son_count )::value_type,
/* OffsetType = */ uint32_t,
/* debug = */ true
> son_scheduler;
typedef generic_far_future_witness_scheduler<
/* WitnessID = */ son_id_type,
/* RNG = */ witness_scheduler_rng,
/* CountType = */ decltype( chain_parameters::extensions.value.maximum_son_count )::value_type,
/* OffsetType = */ uint32_t,
/* debug = */ true
> far_future_son_scheduler;
class witness_schedule_object : public graphene::db::abstract_object<witness_schedule_object>
{
public:
@ -76,9 +92,30 @@ class witness_schedule_object : public graphene::db::abstract_object<witness_sch
fc::uint128_t recent_slots_filled;
};
class son_schedule_object : public graphene::db::abstract_object<son_schedule_object>
{
public:
static const uint8_t space_id = implementation_ids;
static const uint8_t type_id = impl_son_schedule_object_type;
vector< son_id_type > current_shuffled_sons;
son_scheduler scheduler;
uint32_t last_scheduling_block;
uint64_t slots_since_genesis = 0;
std::array< char, sizeof(secret_hash_type) > rng_seed;
/**
* Not necessary for consensus, but used for figuring out the participation rate.
* The nth bit is 0 if the nth slot was unfilled, else it is 1.
*/
fc::uint128_t recent_slots_filled;
};
} }
MAP_OBJECT_ID_TO_TYPE(graphene::chain::witness_schedule_object)
MAP_OBJECT_ID_TO_TYPE(graphene::chain::son_schedule_object)
FC_REFLECT( graphene::chain::witness_scheduler,
(_turns)
@ -101,5 +138,26 @@ FC_REFLECT_DERIVED(
(current_shuffled_witnesses)
)
FC_REFLECT( graphene::chain::son_scheduler,
(_turns)
(_tokens)
(_min_token_count)
(_ineligible_waiting_for_token)
(_ineligible_no_turn)
(_eligible)
(_schedule)
(_lame_duck)
)
FC_REFLECT_DERIVED(
graphene::chain::son_schedule_object,
(graphene::db::object),
(scheduler)
(last_scheduling_block)
(slots_since_genesis)
(rng_seed)
(recent_slots_filled)
(current_shuffled_sons)
)
GRAPHENE_EXTERNAL_SERIALIZATION( extern, graphene::chain::witness_scheduler )
GRAPHENE_EXTERNAL_SERIALIZATION( extern, graphene::chain::witness_schedule_object )

View file

@ -1,5 +1,9 @@
#include <graphene/chain/nft_evaluator.hpp>
#include <graphene/protocol/nft_ops.hpp>
#include <graphene/protocol/vote.hpp>
#include <graphene/chain/nft_object.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/chain/hardfork.hpp>
namespace graphene { namespace chain {
@ -18,6 +22,10 @@ void_result nft_metadata_create_evaluator::do_evaluate( const nft_metadata_creat
(*op.revenue_partner)(db());
FC_ASSERT(*op.revenue_split >= 0 && *op.revenue_split <= GRAPHENE_100_PERCENT, "Revenue split percent invalid");
}
if(op.account_role) {
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");
}
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -32,6 +40,7 @@ object_id_type nft_metadata_create_evaluator::do_apply( const nft_metadata_creat
obj.revenue_split = op.revenue_split;
obj.is_transferable = op.is_transferable;
obj.is_sellable = op.is_sellable;
obj.account_role = op.account_role;
});
return new_nft_metadata_object.id;
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -57,6 +66,10 @@ void_result nft_metadata_update_evaluator::do_evaluate( const nft_metadata_updat
(*op.revenue_partner)(db());
FC_ASSERT(*op.revenue_split >= 0 && *op.revenue_split <= GRAPHENE_100_PERCENT, "Revenue split percent invalid");
}
if(op.account_role) {
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");
}
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -77,6 +90,8 @@ void_result nft_metadata_update_evaluator::do_apply( const nft_metadata_update_o
obj.is_transferable = *op.is_transferable;
if( op.is_sellable.valid() )
obj.is_sellable = *op.is_sellable;
if( op.account_role.valid() )
obj.account_role = op.account_role;
});
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -144,6 +159,17 @@ void_result nft_safe_transfer_from_evaluator::do_evaluate( const nft_safe_transf
const auto& nft_meta_obj = itr_nft->nft_metadata_id(db());
FC_ASSERT( nft_meta_obj.is_transferable == true, "NFT is not transferable");
if (nft_meta_obj.account_role)
{
const auto &ar_idx = db().get_index_type<account_role_index>().indices().get<by_id>();
auto ar_itr = ar_idx.find(*nft_meta_obj.account_role);
if(ar_itr != ar_idx.end())
{
FC_ASSERT(db().account_role_valid(*ar_itr, op.operator_, get_type()), "Account role not valid");
FC_ASSERT(db().account_role_valid(*ar_itr, op.to), "Account role not valid");
}
}
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -2,6 +2,8 @@
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/nft_object.hpp>
#include <graphene/protocol/operations.hpp>
#include <graphene/chain/account_role_object.hpp>
#include <graphene/chain/exceptions.hpp>
#include <graphene/chain/hardfork.hpp>
#include <graphene/chain/is_authorized_asset.hpp>
@ -38,6 +40,15 @@ namespace graphene
}
const auto &nft_meta_obj = nft_obj.nft_metadata_id(d);
FC_ASSERT(nft_meta_obj.is_sellable == true, "NFT is not sellable");
if (nft_meta_obj.account_role)
{
const auto &ar_idx = db().get_index_type<account_role_index>().indices().get<by_id>();
auto ar_itr = ar_idx.find(*nft_meta_obj.account_role);
if(ar_itr != ar_idx.end())
{
FC_ASSERT(db().account_role_valid(*ar_itr, op.issuer, get_type()), "Account role not valid");
}
}
}
FC_ASSERT(op.offer_expiration_date > d.head_block_time(), "Expiration should be in future");
FC_ASSERT(op.fee.amount >= 0, "Invalid fee");
@ -83,6 +94,7 @@ namespace graphene
auto now = d.head_block_time();
FC_ASSERT(now >= HARDFORK_NFT_TIME, "Not allowed until NFT HF");
const auto &offer = op.offer_id(d);
op.bidder(d);
for (const auto &item : offer.item_ids)
{
const auto &nft_obj = item(d);
@ -99,6 +111,18 @@ namespace graphene
FC_ASSERT(!is_approved, "Bidder cannot already be an approved account of the item");
FC_ASSERT(!is_approved_operator, "Bidder cannot already be an approved operator of the item");
}
const auto &nft_meta_obj = nft_obj.nft_metadata_id(d);
FC_ASSERT(nft_meta_obj.is_sellable == true, "NFT is not sellable");
if (nft_meta_obj.account_role)
{
const auto &ar_idx = db().get_index_type<account_role_index>().indices().get<by_id>();
auto ar_itr = ar_idx.find(*nft_meta_obj.account_role);
if(ar_itr != ar_idx.end())
{
FC_ASSERT(db().account_role_valid(*ar_itr, op.bidder, get_type()), "Account role not valid");
}
}
}
FC_ASSERT(op.bid_price.asset_id == offer.minimum_price.asset_id, "Asset type mismatch");

View file

@ -25,6 +25,7 @@
#include <graphene/chain/proposal_evaluator.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/son_proposal_object.hpp>
#include <graphene/protocol/account.hpp>
#include <graphene/protocol/fee_schedule.hpp>
#include <graphene/protocol/tournament.hpp>
@ -61,10 +62,18 @@ struct proposal_operation_hardfork_visitor
FC_ASSERT( !aco.extensions.value.affiliate_distributions.valid(), "Affiliate reward distributions not allowed yet" );
}
void operator()(const sport_create_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "sport_create_operation not allowed yet!" );
}
void operator()(const sport_update_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "sport_update_operation not allowed yet!" );
}
void operator()(const sport_delete_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "sport_delete_operation not allowed yet!" );
}
void operator()(const event_group_create_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_group_create_operation not allowed yet!" );
}
@ -73,6 +82,10 @@ struct proposal_operation_hardfork_visitor
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_group_update_operation not allowed yet!" );
}
void operator()(const event_group_delete_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_group_delete_operation not allowed yet!" );
}
void operator()(const event_create_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_create_operation not allowed yet!" );
}
@ -110,7 +123,7 @@ struct proposal_operation_hardfork_visitor
}
void operator()(const bet_cancel_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "betting_market_group_resolve_operation not allowed yet!" );
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "bet_cancel_operation not allowed yet!" );
}
void operator()(const betting_market_group_update_operation &v) const {
@ -127,7 +140,7 @@ struct proposal_operation_hardfork_visitor
void operator()(const vesting_balance_create_operation &vbco) const {
if(block_time < HARDFORK_GPOS_TIME)
FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" );
FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" );
}
void operator()(const custom_permission_create_operation &v) const {
@ -194,6 +207,41 @@ struct proposal_operation_hardfork_visitor
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "nft_set_approval_for_all_operation not allowed yet!" );
}
void operator()(const account_role_create_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "account_role_create_operation not allowed yet!" );
}
void operator()(const account_role_update_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "account_role_update_operation not allowed yet!" );
}
void operator()(const account_role_delete_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_NFT_TIME, "account_role_delete_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!" );
}
void operator()(const son_update_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_update_operation not allowed yet!" );
}
void operator()(const son_deregister_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_deregister_operation not allowed yet!" );
}
void operator()(const son_heartbeat_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_heartbeat_operation not allowed yet!" );
}
void operator()(const son_report_down_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_report_down_operation not allowed yet!" );
}
void operator()(const son_maintenance_operation &v) const {
FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_maintenance_operation not allowed yet!" );
}
// loop and self visit in proposals
void operator()(const proposal_create_operation &v) const {
@ -202,19 +250,38 @@ struct proposal_operation_hardfork_visitor
}
};
void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o)
void son_hardfork_visitor::operator()( const son_deregister_operation &v )
{
db.create<son_proposal_object>([&]( son_proposal_object& son_prop ) {
son_prop.proposal_type = son_proposal_type::son_deregister_proposal;
son_prop.proposal_id = prop_id;
son_prop.son_id = v.son_id;
});
}
void son_hardfork_visitor::operator()( const son_report_down_operation &v )
{
db.create<son_proposal_object>([&]( son_proposal_object& son_prop ) {
son_prop.proposal_type = son_proposal_type::son_report_down_proposal;
son_prop.proposal_id = prop_id;
son_prop.son_id = v.son_id;
});
}
void_result proposal_create_evaluator::do_evaluate( const proposal_create_operation& o )
{ try {
const database& d = db();
auto block_time = d.head_block_time();
proposal_operation_hardfork_visitor vtor( d.head_block_time() );
proposal_operation_hardfork_visitor vtor( block_time );
vtor( o );
const auto& global_parameters = d.get_global_properties().parameters;
FC_ASSERT( o.expiration_time > d.head_block_time(), "Proposal has already expired on creation." );
FC_ASSERT( o.expiration_time <= d.head_block_time() + global_parameters.maximum_proposal_lifetime,
FC_ASSERT( o.expiration_time > block_time, "Proposal has already expired on creation." );
FC_ASSERT( o.expiration_time <= block_time + global_parameters.maximum_proposal_lifetime,
"Proposal expiration time is too far in the future.");
FC_ASSERT( !o.review_period_seconds || fc::seconds(*o.review_period_seconds) < (o.expiration_time - d.head_block_time()),
FC_ASSERT( !o.review_period_seconds || fc::seconds(*o.review_period_seconds) < (o.expiration_time - block_time),
"Proposal review period must be less than its overall lifetime." );
{
@ -223,7 +290,8 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
vector<authority> other;
for( auto& op : o.proposed_ops )
{
operation_get_required_authorities(op.op, auths, auths, other);
operation_get_required_authorities( op.op, auths, auths, other,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(block_time) );
}
FC_ASSERT( other.size() == 0 ); // TODO: what about other???
@ -246,18 +314,19 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
}
}
for( const op_wrapper& op : o.proposed_ops )
for (const op_wrapper& op : o.proposed_ops)
_proposed_trx.operations.push_back(op.op);
_proposed_trx.validate();
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }
object_id_type proposal_create_evaluator::do_apply(const proposal_create_operation& o)
object_id_type proposal_create_evaluator::do_apply( const proposal_create_operation& o )
{ try {
database& d = db();
auto chain_time = d.head_block_time();
const proposal_object& proposal = d.create<proposal_object>([&](proposal_object& proposal) {
const proposal_object& proposal = d.create<proposal_object>( [&o, this, chain_time](proposal_object& proposal) {
_proposed_trx.expiration = o.expiration_time;
proposal.proposed_transaction = _proposed_trx;
proposal.proposer = o.fee_paying_account;
@ -271,7 +340,8 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
// TODO: consider caching values from evaluate?
for( auto& op : _proposed_trx.operations )
operation_get_required_authorities(op, required_active, proposal.required_owner_approvals, other);
operation_get_required_authorities( op, required_active, proposal.required_owner_approvals, other,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time) );
//All accounts which must provide both owner and active authority should be omitted from the active authority set;
//owner authority approval implies active authority approval.
@ -280,10 +350,16 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
std::inserter(proposal.required_active_approvals, proposal.required_active_approvals.begin()));
});
son_hardfork_visitor son_vtor(d, proposal.id);
for(auto& op: o.proposed_ops)
{
op.op.visit(son_vtor);
}
return proposal.id;
} FC_CAPTURE_AND_RETHROW( (o) ) }
void_result proposal_update_evaluator::do_evaluate(const proposal_update_operation& o)
void_result proposal_update_evaluator::do_evaluate( const proposal_update_operation& o )
{ try {
database& d = db();

View file

@ -24,12 +24,13 @@
#include <graphene/chain/database.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/hardfork.hpp>
namespace graphene { namespace chain {
bool proposal_object::is_authorized_to_execute(database& db) const
bool proposal_object::is_authorized_to_execute( database& db ) const
{
transaction_evaluation_state dry_run_eval(&db);
transaction_evaluation_state dry_run_eval( &db );
try {
verify_authority( proposed_transaction.operations,
@ -38,6 +39,7 @@ bool proposal_object::is_authorized_to_execute(database& db) const
[&]( account_id_type id ){ return &id(db).owner; },
[&]( account_id_type id, const operation& op ){
return db.get_account_custom_authorities(id, op); },
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ),
db.get_global_properties().parameters.max_authority_depth,
true, /* allow committee */
available_active_approvals,

Some files were not shown because too many files have changed in this diff Show more